addons/docs/src/frameworks/react/lib/inspection/acornParser.test.ts
import { parse } from './acornParser';
import {
InspectionType,
InspectionElement,
InspectionObject,
InspectionArray,
InspectionIdentifier,
InspectionLiteral,
InspectionFunction,
InspectionUnknown,
} from './types';
describe('parse', () => {
describe('expression', () => {
it('support HTML element', () => {
const result = parse('<div>Hello!</div>');
const inferredType = result.inferredType as InspectionElement;
expect(inferredType.type).toBe(InspectionType.ELEMENT);
expect(inferredType.identifier).toBe('div');
expect(result.ast).toBeDefined();
});
it('support React declaration', () => {
const result = parse('<FunctionalComponent />');
const inferredType = result.inferredType as InspectionElement;
expect(inferredType.type).toBe(InspectionType.ELEMENT);
expect(inferredType.identifier).toBe('FunctionalComponent');
expect(result.ast).toBeDefined();
});
it('support anonymous functional React component', () => {
const result = parse('() => { return <div>Hey!</div>; }');
const inferredType = result.inferredType as InspectionElement;
expect(inferredType.type).toBe(InspectionType.ELEMENT);
expect(inferredType.identifier).toBeUndefined();
expect(result.ast).toBeDefined();
});
it('support named functional React component', () => {
const result = parse('function NamedFunctionalComponent() { return <div>Hey!</div>; }');
const inferredType = result.inferredType as InspectionElement;
expect(inferredType.type).toBe(InspectionType.ELEMENT);
expect(inferredType.identifier).toBe('NamedFunctionalComponent');
expect(result.ast).toBeDefined();
});
it('support class React component', () => {
const result = parse(`
class ClassComponent extends React.PureComponent {
render() {
return <div>Hey!</div>;
}
}`);
const inferredType = result.inferredType as InspectionElement;
expect(inferredType.type).toBe(InspectionType.ELEMENT);
expect(inferredType.identifier).toBe('ClassComponent');
expect(result.ast).toBeDefined();
});
it('support PropTypes.shape', () => {
const result = parse('PropTypes.shape({ foo: PropTypes.string })');
const inferredType = result.inferredType as InspectionObject;
expect(inferredType.type).toBe(InspectionType.OBJECT);
expect(inferredType.depth).toBe(1);
expect(result.ast).toBeDefined();
});
it('support deep PropTypes.shape', () => {
const result = parse('PropTypes.shape({ foo: PropTypes.shape({ bar: PropTypes.string }) })');
const inferredType = result.inferredType as InspectionObject;
expect(inferredType.type).toBe(InspectionType.OBJECT);
expect(inferredType.depth).toBe(2);
expect(result.ast).toBeDefined();
});
it('support shape', () => {
const result = parse('shape({ foo: string })');
const inferredType = result.inferredType as InspectionObject;
expect(inferredType.type).toBe(InspectionType.OBJECT);
expect(inferredType.depth).toBe(1);
expect(result.ast).toBeDefined();
});
it('support deep shape', () => {
const result = parse('shape({ foo: shape({ bar: string }) })');
const inferredType = result.inferredType as InspectionObject;
expect(inferredType.type).toBe(InspectionType.OBJECT);
expect(inferredType.depth).toBe(2);
expect(result.ast).toBeDefined();
});
it('support single prop object literal', () => {
const result = parse('{ foo: PropTypes.string }');
const inferredType = result.inferredType as InspectionObject;
expect(inferredType.type).toBe(InspectionType.OBJECT);
expect(inferredType.depth).toBe(1);
expect(result.ast).toBeDefined();
});
it('support multi prop object literal', () => {
const result = parse(`
{
foo: PropTypes.string,
bar: PropTypes.string
}`);
const inferredType = result.inferredType as InspectionObject;
expect(inferredType.type).toBe(InspectionType.OBJECT);
expect(inferredType.depth).toBe(1);
expect(result.ast).toBeDefined();
});
it('support deep object literal', () => {
const result = parse(`
{
foo: {
hey: PropTypes.string
},
bar: PropTypes.string,
hey: {
ho: PropTypes.string
}
}`);
const inferredType = result.inferredType as InspectionObject;
expect(inferredType.type).toBe(InspectionType.OBJECT);
expect(inferredType.depth).toBe(2);
expect(result.ast).toBeDefined();
});
it('support required prop', () => {
const result = parse('{ foo: PropTypes.string.isRequired }');
const inferredType = result.inferredType as InspectionObject;
expect(inferredType.type).toBe(InspectionType.OBJECT);
expect(inferredType.depth).toBe(1);
expect(result.ast).toBeDefined();
});
it('support array', () => {
const result = parse("['bottom-left', 'botton-center', 'bottom-right']");
const inferredType = result.inferredType as InspectionArray;
expect(inferredType.type).toBe(InspectionType.ARRAY);
expect(inferredType.depth).toBe(1);
expect(result.ast).toBeDefined();
});
it('support deep array', () => {
const result = parse("['bottom-left', { foo: string }, [['hey', 'ho']]]");
const inferredType = result.inferredType as InspectionArray;
expect(inferredType.type).toBe(InspectionType.ARRAY);
expect(inferredType.depth).toBe(3);
expect(result.ast).toBeDefined();
});
it('support object identifier', () => {
const result = parse('NAMED_OBJECT');
const inferredType = result.inferredType as InspectionIdentifier;
expect(inferredType.type).toBe(InspectionType.IDENTIFIER);
expect(inferredType.identifier).toBe('NAMED_OBJECT');
expect(result.ast).toBeDefined();
});
it('support anonymous function', () => {
const result = parse('() => {}');
const inferredType = result.inferredType as InspectionFunction;
expect(inferredType.type).toBe(InspectionType.FUNCTION);
expect(inferredType.identifier).toBeUndefined();
expect(inferredType.hasParams).toBeFalsy();
expect(inferredType.params.length).toBe(0);
expect(result.ast).toBeDefined();
});
it('support anonymous function with arguments', () => {
const result = parse('(a, b) => {}');
const inferredType = result.inferredType as InspectionFunction;
expect(inferredType.type).toBe(InspectionType.FUNCTION);
expect(inferredType.identifier).toBeUndefined();
expect(inferredType.hasParams).toBeTruthy();
expect(inferredType.params.length).toBe(2);
expect(result.ast).toBeDefined();
});
it('support named function', () => {
const result = parse('function concat() {}');
const inferredType = result.inferredType as InspectionFunction;
expect(inferredType.type).toBe(InspectionType.FUNCTION);
expect(inferredType.identifier).toBe('concat');
expect(inferredType.hasParams).toBeFalsy();
expect(inferredType.params.length).toBe(0);
expect(result.ast).toBeDefined();
});
it('support named function with arguments', () => {
const result = parse('function concat(a, b) {}');
const inferredType = result.inferredType as InspectionFunction;
expect(inferredType.type).toBe(InspectionType.FUNCTION);
expect(inferredType.identifier).toBe('concat');
expect(inferredType.hasParams).toBeTruthy();
expect(inferredType.params.length).toBe(2);
expect(result.ast).toBeDefined();
});
it('support class', () => {
const result = parse('class Foo {}');
const inferredType = result.inferredType as InspectionFunction;
expect(inferredType.type).toBe(InspectionType.CLASS);
expect(inferredType.identifier).toBe('Foo');
expect(result.ast).toBeDefined();
});
[
{ name: 'string', value: "'string value'" },
{ name: 'numeric', value: '1' },
{ name: 'boolean (true)', value: 'true' },
{ name: 'boolean (false)', value: 'false' },
{ name: 'null', value: 'null' },
].forEach((x) => {
it(`support ${x.name}`, () => {
const result = parse(x.value);
const inferredType = result.inferredType as InspectionLiteral;
expect(inferredType.type).toBe(InspectionType.LITERAL);
expect(result.ast).toBeDefined();
});
});
it("returns Unknown when it's not supported", () => {
const result = parse("Symbol('foo')");
const inferredType = result.inferredType as InspectionUnknown;
expect(inferredType.type).toBe(InspectionType.UNKNOWN);
expect(result.ast).toBeDefined();
});
});
});