Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Addon-docs: Fix type aliases and enum types from Angular Compodoc JSON #12665

Merged
merged 10 commits into from Dec 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
96 changes: 94 additions & 2 deletions addons/docs/src/frameworks/angular/compodoc.test.ts
@@ -1,5 +1,5 @@
import { extractType } from './compodoc';
import { Decorator } from './types';
import { extractType, setCompodocJson } from './compodoc';
import { CompodocJson, Decorator } from './types';

const makeProperty = (compodocType?: string) => ({
type: compodocType,
Expand All @@ -8,8 +8,96 @@ const makeProperty = (compodocType?: string) => ({
optional: true,
});

const getDummyCompodocJson = () => {
return {
miscellaneous: {
typealiases: [
{
name: 'EnumAlias',
ctype: 'miscellaneous',
subtype: 'typealias',
rawtype: 'EnumNumeric',
file: 'src/stories/component-with-enums/enums.component.ts',
description: '',
kind: 161,
},
{
name: 'TypeAlias',
ctype: 'miscellaneous',
subtype: 'typealias',
rawtype: '"Type Alias 1" | "Type Alias 2" | "Type Alias 3"',
file: 'src/stories/component-with-enums/enums.component.ts',
description: '',
kind: 168,
},
],
enumerations: [
{
name: 'EnumNumeric',
childs: [
{
name: 'FIRST',
},
{
name: 'SECOND',
},
{
name: 'THIRD',
},
],
ctype: 'miscellaneous',
subtype: 'enum',
description: '<p>Button Priority</p>\n',
file: 'src/stories/component-with-enums/enums.component.ts',
},
{
name: 'EnumNumericInitial',
childs: [
{
name: 'UNO',
value: '1',
},
{
name: 'DOS',
},
{
name: 'TRES',
},
],
ctype: 'miscellaneous',
subtype: 'enum',
description: '',
file: 'src/stories/component-with-enums/enums.component.ts',
},
{
name: 'EnumStringValues',
childs: [
{
name: 'PRIMARY',
value: 'PRIMARY',
},
{
name: 'SECONDARY',
value: 'SECONDARY',
},
{
name: 'TERTIARY',
value: 'TERTIARY',
},
],
ctype: 'miscellaneous',
subtype: 'enum',
description: '',
file: 'src/stories/component-with-enums/enums.component.ts',
},
],
},
} as CompodocJson;
};

describe('extractType', () => {
describe('with compodoc type', () => {
setCompodocJson(getDummyCompodocJson());
it.each([
['string', { name: 'string' }],
['boolean', { name: 'boolean' }],
Expand All @@ -21,6 +109,10 @@ describe('extractType', () => {
['T[]', { name: 'object' }],
['[]', { name: 'object' }],
['"primary" | "secondary"', { name: 'enum', value: ['primary', 'secondary'] }],
['TypeAlias', { name: 'enum', value: ['Type Alias 1', 'Type Alias 2', 'Type Alias 3'] }],
['EnumNumeric', { name: 'object' }],
['EnumNumericInitial', { name: 'object' }],
['EnumStringValues', { name: 'enum', value: ['PRIMARY', 'SECONDARY', 'TERTIARY'] }],
])('%s', (compodocType, expected) => {
expect(extractType(makeProperty(compodocType), null)).toEqual(expected);
});
Expand Down
20 changes: 17 additions & 3 deletions addons/docs/src/frameworks/angular/compodoc.ts
Expand Up @@ -25,7 +25,7 @@ export const setCompodocJson = (compodocJson: CompodocJson) => {
};

// @ts-ignore
export const getCompdocJson = (): CompodocJson => window.__STORYBOOK_COMPODOC_JSON__;
export const getCompodocJson = (): CompodocJson => window.__STORYBOOK_COMPODOC_JSON__;

export const checkValidComponentOrDirective = (component: Component | Directive) => {
if (!component.name) {
Expand Down Expand Up @@ -90,7 +90,7 @@ const getComponentData = (component: Component | Directive) => {
return null;
}
checkValidComponentOrDirective(component);
const compodocJson = getCompdocJson();
const compodocJson = getCompodocJson();
checkValidCompodocJson(compodocJson);
const { name } = component;
const metadata = findComponentByName(name, compodocJson);
Expand All @@ -113,6 +113,13 @@ const extractTypeFromValue = (defaultValue: any) => {
};

const extractEnumValues = (compodocType: any) => {
const compodocJson = getCompodocJson();
const enumType = compodocJson?.miscellaneous.enumerations.find((x) => x.name === compodocType);

if (enumType?.childs.every((x) => x.value)) {
return enumType.childs.map((x) => x.value);
}

if (typeof compodocType !== 'string' || compodocType.indexOf('|') === -1) {
return null;
}
Expand All @@ -135,7 +142,8 @@ export const extractType = (property: Property, defaultValue: any) => {
case null:
return { name: 'void' };
default: {
const enumValues = extractEnumValues(compodocType);
const resolvedType = resolveTypealias(compodocType);
const enumValues = extractEnumValues(resolvedType);
return enumValues ? { name: 'enum', value: enumValues } : { name: 'object' };
}
}
Expand All @@ -152,6 +160,12 @@ const extractDefaultValue = (property: Property) => {
}
};

const resolveTypealias = (compodocType: string): string => {
const compodocJson = getCompodocJson();
const typeAlias = compodocJson?.miscellaneous.typealiases.find((x) => x.name === compodocType);
return typeAlias ? resolveTypealias(typeAlias.rawtype) : compodocType;
};

export const extractArgTypesFromData = (componentData: Class | Directive | Injectable | Pipe) => {
const sectionToItems: Record<string, ArgType[]> = {};
const compodocClasses = ['component', 'directive'].includes(componentData.type)
Expand Down
30 changes: 30 additions & 0 deletions addons/docs/src/frameworks/angular/types.ts
Expand Up @@ -66,10 +66,40 @@ export interface Decorator {
name: string;
}

export interface TypeAlias {
name: string;
ctype: string;
subtype: string;
rawtype: string;
file: string;
kind: number;
description?: string;
rawdescription?: string;
}

export interface EnumType {
name: string;
childs: EnumTypeChild[];
ctype: string;
subtype: string;
file: string;
description?: string;
rawdescription?: string;
}

export interface EnumTypeChild {
name: string;
value?: string;
}

export interface CompodocJson {
directives: Directive[];
components: Component[];
pipes: Pipe[];
injectables: Injectable[];
classes: Class[];
miscellaneous?: {
typealiases?: TypeAlias[];
enumerations?: EnumType[];
};
}
@@ -0,0 +1,32 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Storyshots Enum Types Basic 1`] = `
<storybook-dynamic-app-root
cfr={[Function CodegenComponentFactoryResolver]}
data={[Function Object]}
target={[Function ViewContainerRef_]}
>
<app-enums>
<div>
<div>
unionType: union a
</div>
<div>
aliasedUnionType: Type Alias 1
</div>
<div>
enumNumeric:
</div>
<div>
enumNumericInitial: 1
</div>
<div>
enumStrings: PRIMARY
</div>
<div>
enumAlias:
</div>
</div>
</app-enums>
</storybook-dynamic-app-root>
`;
@@ -0,0 +1,8 @@
<div>
<div>unionType: {{ unionType }}</div>
<div>aliasedUnionType: {{ aliasedUnionType }}</div>
<div>enumNumeric: {{ enumNumeric }}</div>
<div>enumNumericInitial: {{ enumNumericInitial }}</div>
<div>enumStrings: {{ enumStrings }}</div>
<div>enumAlias: {{ enumAlias }}</div>
</div>
@@ -0,0 +1,25 @@
import { Story, Meta } from '@storybook/angular';
import {
EnumsComponent,
EnumNumeric,
EnumNumericInitial,
EnumStringValues,
} from './enums.component';

export default {
title: 'Enum Types',
component: EnumsComponent,
} as Meta;

export const Basic: Story = (args) => ({
component: EnumsComponent,
props: args,
});
Basic.args = {
unionType: 'union a',
aliasedUnionType: 'Type Alias 1',
enumNumeric: EnumNumeric.FIRST,
enumNumericInitial: EnumNumericInitial.UNO,
enumStrings: EnumStringValues.PRIMARY,
enumAlias: EnumNumeric.FIRST,
};
@@ -0,0 +1,53 @@
import { Component, Input } from '@angular/core';

/**
* This component is used for testing the various forms of enum types
*/
@Component({
selector: 'app-enums',
templateUrl: './enums.component.html',
})
export class EnumsComponent {
/** Union Type of string literals */
@Input() unionType: 'Union A' | 'Union B' | 'Union C';

/** Union Type assigned as a Type Alias */
@Input() aliasedUnionType: TypeAlias;

/** Base Enum Type with no assigned values */
@Input() enumNumeric: EnumNumeric;

/** Enum with initial numeric value and auto-incrementing subsequent values */
@Input() enumNumericInitial: EnumNumericInitial;

/** Enum with string values */
@Input() enumStrings: EnumStringValues;

/** Type Aliased Enum Type */
@Input() enumAlias: EnumAlias;
}

/**
* Button Priority
*/
export enum EnumNumeric {
FIRST,
SECOND,
THIRD,
}

export enum EnumNumericInitial {
UNO = 1,
DOS,
TRES,
}

export enum EnumStringValues {
PRIMARY = 'PRIMARY',
SECONDARY = 'SECONDARY',
TERTIARY = 'TERTIARY',
}

export type EnumAlias = EnumNumeric;

type TypeAlias = 'Type Alias 1' | 'Type Alias 2' | 'Type Alias 3';