mirror of
				https://github.com/strapi/strapi.git
				synced 2025-11-04 03:43:34 +00:00 
			
		
		
		
	Add unit tests for typescript generators utils
This commit is contained in:
		
							parent
							
								
									3b48fd1fcb
								
							
						
					
					
						commit
						fa240cfee3
					
				@ -0,0 +1,362 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
const ts = require('typescript');
 | 
			
		||||
const { factory } = require('typescript');
 | 
			
		||||
 | 
			
		||||
const {
 | 
			
		||||
  getAllStrapiSchemas,
 | 
			
		||||
  getDefinitionAttributesCount,
 | 
			
		||||
  getSchemaExtendsTypeName,
 | 
			
		||||
  getSchemaInterfaceName,
 | 
			
		||||
  getSchemaModelType,
 | 
			
		||||
  getTypeNode,
 | 
			
		||||
  toTypeLitteral,
 | 
			
		||||
} = require('../../../generators/schemas/utils');
 | 
			
		||||
 | 
			
		||||
describe('Utils', () => {
 | 
			
		||||
  describe('Get All Strapi Schemas', () => {
 | 
			
		||||
    test('Get both components and content types', () => {
 | 
			
		||||
      const strapi = {
 | 
			
		||||
        contentTypes: {
 | 
			
		||||
          ctA: {},
 | 
			
		||||
          ctB: {},
 | 
			
		||||
        },
 | 
			
		||||
        components: {
 | 
			
		||||
          comp1: {},
 | 
			
		||||
          comp2: {},
 | 
			
		||||
          comp3: {},
 | 
			
		||||
        },
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      const schemas = getAllStrapiSchemas(strapi);
 | 
			
		||||
 | 
			
		||||
      expect(schemas).toMatchObject({ ctA: {}, ctB: {}, comp1: {}, comp2: {}, comp3: {} });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Get only components if there is no content type', () => {
 | 
			
		||||
      const strapi = {
 | 
			
		||||
        contentTypes: {},
 | 
			
		||||
 | 
			
		||||
        components: {
 | 
			
		||||
          comp1: {},
 | 
			
		||||
          comp2: {},
 | 
			
		||||
          comp3: {},
 | 
			
		||||
        },
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      const schemas = getAllStrapiSchemas(strapi);
 | 
			
		||||
 | 
			
		||||
      expect(schemas).toMatchObject({ comp1: {}, comp2: {}, comp3: {} });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Get only content types if there is no component', () => {
 | 
			
		||||
      const strapi = {
 | 
			
		||||
        contentTypes: {
 | 
			
		||||
          ctA: {},
 | 
			
		||||
          ctB: {},
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        components: {},
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      const schemas = getAllStrapiSchemas(strapi);
 | 
			
		||||
 | 
			
		||||
      expect(schemas).toMatchObject({ ctA: {}, ctB: {} });
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('Get Definition Attributes Count', () => {
 | 
			
		||||
    const createMainNode = (members = []) => {
 | 
			
		||||
      return factory.createInterfaceDeclaration(
 | 
			
		||||
        undefined,
 | 
			
		||||
        undefined,
 | 
			
		||||
        factory.createIdentifier('Foo'),
 | 
			
		||||
        undefined,
 | 
			
		||||
        undefined,
 | 
			
		||||
        members
 | 
			
		||||
      );
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const createPropertyDeclaration = (name, type) => {
 | 
			
		||||
      return factory.createPropertyDeclaration(
 | 
			
		||||
        undefined,
 | 
			
		||||
        undefined,
 | 
			
		||||
        factory.createIdentifier(name),
 | 
			
		||||
        undefined,
 | 
			
		||||
        type
 | 
			
		||||
      );
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    test('Returns null if there are no members in the parent node', () => {
 | 
			
		||||
      const mainNode = createMainNode();
 | 
			
		||||
 | 
			
		||||
      const count = getDefinitionAttributesCount(mainNode);
 | 
			
		||||
 | 
			
		||||
      expect(count).toBeNull();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Returns null if there are members in the parent node, but none named "attributes"', () => {
 | 
			
		||||
      const mainNode = createMainNode([
 | 
			
		||||
        createPropertyDeclaration(
 | 
			
		||||
          'bar',
 | 
			
		||||
          factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)
 | 
			
		||||
        ),
 | 
			
		||||
        createPropertyDeclaration(
 | 
			
		||||
          'foobar',
 | 
			
		||||
          factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword)
 | 
			
		||||
        ),
 | 
			
		||||
      ]);
 | 
			
		||||
 | 
			
		||||
      const count = getDefinitionAttributesCount(mainNode);
 | 
			
		||||
 | 
			
		||||
      expect(count).toBeNull();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Returns the number of attributes if the property is present', () => {
 | 
			
		||||
      const mainNode = createMainNode([
 | 
			
		||||
        createPropertyDeclaration(
 | 
			
		||||
          'bar',
 | 
			
		||||
          factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)
 | 
			
		||||
        ),
 | 
			
		||||
        createPropertyDeclaration(
 | 
			
		||||
          'attributes',
 | 
			
		||||
          factory.createTypeLiteralNode([
 | 
			
		||||
            createPropertyDeclaration(
 | 
			
		||||
              'a',
 | 
			
		||||
              factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)
 | 
			
		||||
            ),
 | 
			
		||||
            createPropertyDeclaration(
 | 
			
		||||
              'b',
 | 
			
		||||
              factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword)
 | 
			
		||||
            ),
 | 
			
		||||
            createPropertyDeclaration(
 | 
			
		||||
              'c',
 | 
			
		||||
              factory.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword)
 | 
			
		||||
            ),
 | 
			
		||||
          ])
 | 
			
		||||
        ),
 | 
			
		||||
        createPropertyDeclaration(
 | 
			
		||||
          'foobar',
 | 
			
		||||
          factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword)
 | 
			
		||||
        ),
 | 
			
		||||
      ]);
 | 
			
		||||
 | 
			
		||||
      const count = getDefinitionAttributesCount(mainNode);
 | 
			
		||||
 | 
			
		||||
      expect(count).toBe(3);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test("Returns 0 if the attributes node is present but don't have any members", () => {
 | 
			
		||||
      const mainNode = createMainNode([
 | 
			
		||||
        createPropertyDeclaration('attributes', factory.createTypeLiteralNode()),
 | 
			
		||||
        createPropertyDeclaration(
 | 
			
		||||
          'foobar',
 | 
			
		||||
          factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword)
 | 
			
		||||
        ),
 | 
			
		||||
      ]);
 | 
			
		||||
 | 
			
		||||
      const count = getDefinitionAttributesCount(mainNode);
 | 
			
		||||
 | 
			
		||||
      expect(count).toBe(0);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('Get Schema Model Type', () => {
 | 
			
		||||
    test.each([
 | 
			
		||||
      [{ modelType: 'component', kind: null }, 'component'],
 | 
			
		||||
      [{ modelType: 'contentType', kind: 'singleType' }, 'singleType'],
 | 
			
		||||
      [{ modelType: 'contentType', kind: 'collectionType' }, 'collectionType'],
 | 
			
		||||
      [{ modelType: 'invalidType', kind: 'foo' }, null],
 | 
			
		||||
    ])('%p to be evaluated to %p', (schema, expected) => {
 | 
			
		||||
      expect(getSchemaModelType(schema)).toBe(expected);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('Get Schema Extends Type Name', () => {
 | 
			
		||||
    test.each([
 | 
			
		||||
      [{ modelType: 'component', kind: null }, 'ComponentSchema'],
 | 
			
		||||
      [{ modelType: 'contentType', kind: 'singleType' }, 'SingleTypeSchema'],
 | 
			
		||||
      [{ modelType: 'contentType', kind: 'collectionType' }, 'CollectionTypeSchema'],
 | 
			
		||||
      [{ modelType: 'invalidType', kind: 'foo' }, 'Schema'],
 | 
			
		||||
    ])("Expect %p to generate %p as the base type for a schema's interface", (schema, expected) => {
 | 
			
		||||
      expect(getSchemaExtendsTypeName(schema)).toBe(expected);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('Get Schema Interface Name', () => {
 | 
			
		||||
    test.each([
 | 
			
		||||
      ['api::foo.foo', 'ApiFooFoo'],
 | 
			
		||||
      ['plugin::bar.foo', 'PluginBarFoo'],
 | 
			
		||||
      ['default.dish', 'DefaultDish'],
 | 
			
		||||
    ])('Should transform UID (%p) to interface name (%p)', (uid, interfaceName) => {
 | 
			
		||||
      expect(getSchemaInterfaceName(uid)).toBe(interfaceName);
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('Get Type Node', () => {
 | 
			
		||||
    test('Create a valid type reference node based on the given generic parameters', () => {
 | 
			
		||||
      const node = getTypeNode('FooBar', [
 | 
			
		||||
        factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
 | 
			
		||||
        factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword),
 | 
			
		||||
      ]);
 | 
			
		||||
 | 
			
		||||
      expect(node.typeArguments).toHaveLength(2);
 | 
			
		||||
 | 
			
		||||
      expect(node.typeArguments[0].kind).toBe(ts.SyntaxKind.StringKeyword);
 | 
			
		||||
      expect(node.typeArguments[1].kind).toBe(ts.SyntaxKind.NumberKeyword);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Create a valid empty type reference node', () => {
 | 
			
		||||
      const node = getTypeNode('FooBar');
 | 
			
		||||
 | 
			
		||||
      expect(node.typeArguments).toBeUndefined();
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('To Type Litteral', () => {
 | 
			
		||||
    test('String', () => {
 | 
			
		||||
      const node = toTypeLitteral('foo');
 | 
			
		||||
 | 
			
		||||
      expect(node.kind).toBe(ts.SyntaxKind.StringLiteral);
 | 
			
		||||
      expect(node.text).toBe('foo');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Number', () => {
 | 
			
		||||
      const node = toTypeLitteral(42);
 | 
			
		||||
 | 
			
		||||
      expect(node.kind).toBe(ts.SyntaxKind.FirstLiteralToken);
 | 
			
		||||
      expect(node.text).toBe('42');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Boolean', () => {
 | 
			
		||||
      const trueNode = toTypeLitteral(true);
 | 
			
		||||
      const falseNode = toTypeLitteral(false);
 | 
			
		||||
 | 
			
		||||
      expect(trueNode.kind).toBe(ts.SyntaxKind.TrueKeyword);
 | 
			
		||||
      expect(falseNode.kind).toBe(ts.SyntaxKind.FalseKeyword);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('undefined', () => {
 | 
			
		||||
      const node = toTypeLitteral(undefined);
 | 
			
		||||
 | 
			
		||||
      expect(node.kind).toBe(ts.SyntaxKind.LiteralType);
 | 
			
		||||
      expect(node.literal).toBe(ts.SyntaxKind.UndefinedKeyword);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('null', () => {
 | 
			
		||||
      const node = toTypeLitteral(null);
 | 
			
		||||
 | 
			
		||||
      expect(node.kind).toBe(ts.SyntaxKind.LiteralType);
 | 
			
		||||
      expect(node.literal).toBe(ts.SyntaxKind.NullKeyword);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Array (empty)', () => {
 | 
			
		||||
      const node = toTypeLitteral([]);
 | 
			
		||||
 | 
			
		||||
      expect(node.kind).toBe(ts.SyntaxKind.TupleType);
 | 
			
		||||
      expect(node.elements).toHaveLength(0);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Array (with elements)', () => {
 | 
			
		||||
      const node = toTypeLitteral(['foo', 2]);
 | 
			
		||||
 | 
			
		||||
      expect(node.kind).toBe(ts.SyntaxKind.TupleType);
 | 
			
		||||
      expect(node.elements).toHaveLength(2);
 | 
			
		||||
 | 
			
		||||
      expect(node.elements[0].kind).toBe(ts.SyntaxKind.StringLiteral);
 | 
			
		||||
      expect(node.elements[0].text).toBe('foo');
 | 
			
		||||
 | 
			
		||||
      expect(node.elements[1].kind).toBe(ts.SyntaxKind.FirstLiteralToken);
 | 
			
		||||
      expect(node.elements[1].text).toBe('2');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Array (nested)', () => {
 | 
			
		||||
      const node = toTypeLitteral(['foo', ['bar', 'foobar']]);
 | 
			
		||||
 | 
			
		||||
      expect(node.kind).toBe(ts.SyntaxKind.TupleType);
 | 
			
		||||
      expect(node.elements).toHaveLength(2);
 | 
			
		||||
 | 
			
		||||
      expect(node.elements[0].kind).toBe(ts.SyntaxKind.StringLiteral);
 | 
			
		||||
      expect(node.elements[0].text).toBe('foo');
 | 
			
		||||
 | 
			
		||||
      expect(node.elements[1].kind).toBe(ts.SyntaxKind.TupleType);
 | 
			
		||||
      expect(node.elements[1].elements).toHaveLength(2);
 | 
			
		||||
 | 
			
		||||
      expect(node.elements[1].elements[0].kind).toBe(ts.SyntaxKind.StringLiteral);
 | 
			
		||||
      expect(node.elements[1].elements[0].text).toBe('bar');
 | 
			
		||||
 | 
			
		||||
      expect(node.elements[1].elements[1].kind).toBe(ts.SyntaxKind.StringLiteral);
 | 
			
		||||
      expect(node.elements[1].elements[1].text).toBe('foobar');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Array (with object)', () => {
 | 
			
		||||
      const node = toTypeLitteral([{ foo: 'bar', bar: true }]);
 | 
			
		||||
 | 
			
		||||
      expect(node.kind).toBe(ts.SyntaxKind.TupleType);
 | 
			
		||||
      expect(node.elements).toHaveLength(1);
 | 
			
		||||
 | 
			
		||||
      const objectNode = node.elements[0];
 | 
			
		||||
 | 
			
		||||
      expect(objectNode.kind).toBe(ts.SyntaxKind.TypeLiteral);
 | 
			
		||||
      expect(objectNode.members).toHaveLength(2);
 | 
			
		||||
 | 
			
		||||
      expect(objectNode.members[0].kind).toBe(ts.SyntaxKind.PropertyDeclaration);
 | 
			
		||||
      expect(objectNode.members[0].name.escapedText).toBe('foo');
 | 
			
		||||
      expect(objectNode.members[0].type.kind).toBe(ts.SyntaxKind.StringLiteral);
 | 
			
		||||
      expect(objectNode.members[0].type.text).toBe('bar');
 | 
			
		||||
 | 
			
		||||
      expect(objectNode.members[1].kind).toBe(ts.SyntaxKind.PropertyDeclaration);
 | 
			
		||||
      expect(objectNode.members[1].name.escapedText).toBe('bar');
 | 
			
		||||
      expect(objectNode.members[1].type.kind).toBe(ts.SyntaxKind.TrueKeyword);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Object', () => {
 | 
			
		||||
      const node = toTypeLitteral({ foo: ['bar', true, 2], bar: null });
 | 
			
		||||
 | 
			
		||||
      expect(node.kind).toBe(ts.SyntaxKind.TypeLiteral);
 | 
			
		||||
      expect(node.members).toHaveLength(2);
 | 
			
		||||
 | 
			
		||||
      const [firstMember, secondMember] = node.members;
 | 
			
		||||
 | 
			
		||||
      expect(firstMember.kind).toBe(ts.SyntaxKind.PropertyDeclaration);
 | 
			
		||||
      expect(firstMember.name.escapedText).toBe('foo');
 | 
			
		||||
      expect(firstMember.type.kind).toBe(ts.SyntaxKind.TupleType);
 | 
			
		||||
      expect(firstMember.type.elements).toHaveLength(3);
 | 
			
		||||
      expect(firstMember.type.elements[0].kind).toBe(ts.SyntaxKind.StringLiteral);
 | 
			
		||||
      expect(firstMember.type.elements[1].kind).toBe(ts.SyntaxKind.TrueKeyword);
 | 
			
		||||
      expect(firstMember.type.elements[2].kind).toBe(ts.SyntaxKind.FirstLiteralToken);
 | 
			
		||||
 | 
			
		||||
      expect(secondMember.kind).toBe(ts.SyntaxKind.PropertyDeclaration);
 | 
			
		||||
      expect(secondMember.name.escapedText).toBe('bar');
 | 
			
		||||
      expect(secondMember.type.kind).toBe(ts.SyntaxKind.LiteralType);
 | 
			
		||||
      expect(secondMember.type.literal).toBe(ts.SyntaxKind.NullKeyword);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Object with complex keys', () => {
 | 
			
		||||
      const node = toTypeLitteral({ 'foo-bar': 'foobar', foo: 'bar' });
 | 
			
		||||
 | 
			
		||||
      expect(node.kind).toBe(ts.SyntaxKind.TypeLiteral);
 | 
			
		||||
      expect(node.members).toHaveLength(2);
 | 
			
		||||
 | 
			
		||||
      const [firstMember, secondMember] = node.members;
 | 
			
		||||
 | 
			
		||||
      expect(firstMember.kind).toBe(ts.SyntaxKind.PropertyDeclaration);
 | 
			
		||||
      expect(firstMember.name.kind).toBe(ts.SyntaxKind.StringLiteral);
 | 
			
		||||
      expect(firstMember.name.text).toBe('foo-bar');
 | 
			
		||||
      expect(firstMember.type.kind).toBe(ts.SyntaxKind.StringLiteral);
 | 
			
		||||
      expect(firstMember.type.text).toBe('foobar');
 | 
			
		||||
 | 
			
		||||
      expect(secondMember.kind).toBe(ts.SyntaxKind.PropertyDeclaration);
 | 
			
		||||
      expect(secondMember.name.kind).toBe(ts.SyntaxKind.Identifier);
 | 
			
		||||
      expect(secondMember.name.escapedText).toBe('foo');
 | 
			
		||||
      expect(secondMember.type.kind).toBe(ts.SyntaxKind.StringLiteral);
 | 
			
		||||
      expect(secondMember.type.text).toBe('bar');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    test('Invalid data type supplied (function)', () => {
 | 
			
		||||
      expect(() => toTypeLitteral(() => {})).toThrowError(
 | 
			
		||||
        'Cannot convert to object litteral. Unknown type "function"'
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user