@knapsack/spec-utils 4.78.11--canary.074d651.0 → 4.78.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/.turbo/turbo-lint.log +4 -0
  3. package/.turbo/turbo-test.log +50 -0
  4. package/CHANGELOG.md +12 -0
  5. package/dist/align/align.vtest.d.ts +2 -0
  6. package/dist/align/align.vtest.d.ts.map +1 -0
  7. package/dist/align/align.vtest.js +46 -0
  8. package/dist/align/align.vtest.js.map +1 -0
  9. package/dist/analyze-exports.sandbox-components.vtest.d.ts +2 -0
  10. package/dist/analyze-exports.sandbox-components.vtest.d.ts.map +1 -0
  11. package/dist/analyze-exports.sandbox-components.vtest.js +51 -0
  12. package/dist/analyze-exports.sandbox-components.vtest.js.map +1 -0
  13. package/dist/analyze-exports.vtest.d.ts +2 -0
  14. package/dist/analyze-exports.vtest.d.ts.map +1 -0
  15. package/dist/analyze-exports.vtest.js +160 -0
  16. package/dist/analyze-exports.vtest.js.map +1 -0
  17. package/dist/convert-to-spec.vtest.d.ts +2 -0
  18. package/dist/convert-to-spec.vtest.d.ts.map +1 -0
  19. package/dist/convert-to-spec.vtest.js +131 -0
  20. package/dist/convert-to-spec.vtest.js.map +1 -0
  21. package/dist/get-ts-config.vtest.d.ts +2 -0
  22. package/dist/get-ts-config.vtest.d.ts.map +1 -0
  23. package/dist/get-ts-config.vtest.js +9 -0
  24. package/dist/get-ts-config.vtest.js.map +1 -0
  25. package/dist/resolve.vtest.d.ts +2 -0
  26. package/dist/resolve.vtest.d.ts.map +1 -0
  27. package/dist/resolve.vtest.js +57 -0
  28. package/dist/resolve.vtest.js.map +1 -0
  29. package/dist/utils.vtest.d.ts +2 -0
  30. package/dist/utils.vtest.d.ts.map +1 -0
  31. package/dist/utils.vtest.js +37 -0
  32. package/dist/utils.vtest.js.map +1 -0
  33. package/package.json +10 -10
  34. package/src/align/align.vtest.ts +56 -0
  35. package/src/align/get-exports.bench.ts +28 -0
  36. package/src/align/resolve.bench.ts +20 -0
  37. package/src/align/utils.ts +14 -0
  38. package/src/analyze-exports.sandbox-components.vtest.ts +53 -0
  39. package/src/analyze-exports.ts +54 -0
  40. package/src/analyze-exports.vtest.ts +178 -0
  41. package/src/analyze-symbol.ts +213 -0
  42. package/src/analyze-type.ts +316 -0
  43. package/src/boot.ts +31 -0
  44. package/src/convert-to-spec.ts +196 -0
  45. package/src/convert-to-spec.vtest.ts +136 -0
  46. package/src/get-exports.ts +70 -0
  47. package/src/get-ts-config.ts +96 -0
  48. package/src/get-ts-config.vtest.ts +9 -0
  49. package/src/index.ts +5 -0
  50. package/src/resolve.ts +54 -0
  51. package/src/resolve.vtest.ts +69 -0
  52. package/src/test-fixtures/basics.ts +17 -0
  53. package/src/test-fixtures/functions.ts +50 -0
  54. package/src/test-fixtures/index.ts +2 -0
  55. package/src/types.ts +66 -0
  56. package/src/utils.ts +61 -0
  57. package/src/utils.vtest.ts +39 -0
@@ -0,0 +1,37 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import ts from 'typescript';
3
+ import { getSetFlags } from './utils.js';
4
+ describe('utils tests', () => {
5
+ it('getSetFlags single flag', () => {
6
+ const single = getSetFlags({
7
+ enumObject: ts.SymbolFlags,
8
+ flags: ts.SymbolFlags.Property,
9
+ });
10
+ expect(single).toEqual(['Property']);
11
+ });
12
+ it('getSetFlags multiple flags', () => {
13
+ const multiple = getSetFlags({
14
+ enumObject: ts.SymbolFlags,
15
+ flags:
16
+ // eslint-disable-next-line no-bitwise
17
+ ts.SymbolFlags.FunctionScopedVariable |
18
+ ts.SymbolFlags.BlockScopedVariable,
19
+ });
20
+ expect(multiple).toEqual([
21
+ 'FunctionScopedVariable',
22
+ 'BlockScopedVariable',
23
+ ]);
24
+ });
25
+ it('single flag with multiple flags extracted', () => {
26
+ // an "Accessor" is both a "GetAccessor" and a "SetAccessor"
27
+ const single = getSetFlags({
28
+ enumObject: ts.SymbolFlags,
29
+ flags: ts.SymbolFlags.Accessor,
30
+ });
31
+ expect(single).toEqual([
32
+ 'GetAccessor',
33
+ 'SetAccessor',
34
+ ]);
35
+ });
36
+ });
37
+ //# sourceMappingURL=utils.vtest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.vtest.js","sourceRoot":"","sources":["../src/utils.vtest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,MAAM,GAAG,WAAW,CAAC;YACzB,UAAU,EAAE,EAAE,CAAC,WAAW;YAC1B,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ;SAC/B,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,CAAyB,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,QAAQ,GAAG,WAAW,CAAC;YAC3B,UAAU,EAAE,EAAE,CAAC,WAAW;YAC1B,KAAK;YACH,sCAAsC;YACtC,EAAE,CAAC,WAAW,CAAC,sBAAsB;gBACrC,EAAE,CAAC,WAAW,CAAC,mBAAmB;SACrC,CAAC,CAAC;QACH,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC;YACvB,wBAAwB;YACxB,qBAAqB;SACI,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,4DAA4D;QAC5D,MAAM,MAAM,GAAG,WAAW,CAAC;YACzB,UAAU,EAAE,EAAE,CAAC,WAAW;YAC1B,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ;SAC/B,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;YACrB,aAAa;YACb,aAAa;SACU,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@knapsack/spec-utils",
3
3
  "description": "",
4
- "version": "4.78.11--canary.074d651.0",
4
+ "version": "4.78.11",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  ".": {
@@ -20,17 +20,17 @@
20
20
  "test": "vitest run"
21
21
  },
22
22
  "dependencies": {
23
- "@knapsack/utils": "4.78.11--canary.074d651.0",
23
+ "@knapsack/utils": "4.78.11",
24
24
  "typescript": "^5.8.3"
25
25
  },
26
26
  "devDependencies": {
27
- "@knapsack/angular-sandbox-components": "4.78.11--canary.074d651.0",
28
- "@knapsack/eslint-config-starter": "4.78.11--canary.074d651.0",
29
- "@knapsack/file-utils": "4.78.11--canary.074d651.0",
30
- "@knapsack/prettier-config": "4.78.11--canary.074d651.0",
31
- "@knapsack/sandbox-components": "4.78.11--canary.074d651.0",
32
- "@knapsack/types": "4.78.11--canary.074d651.0",
33
- "@knapsack/typescript-config-starter": "4.78.11--canary.074d651.0",
27
+ "@knapsack/angular-sandbox-components": "4.78.11",
28
+ "@knapsack/eslint-config-starter": "4.78.11",
29
+ "@knapsack/file-utils": "4.78.11",
30
+ "@knapsack/prettier-config": "4.78.11",
31
+ "@knapsack/sandbox-components": "4.78.11",
32
+ "@knapsack/types": "4.78.11",
33
+ "@knapsack/typescript-config-starter": "4.78.11",
34
34
  "@mui/material": "^5.17.1",
35
35
  "@types/node": "^20.17.24",
36
36
  "eslint": "^8.57.0",
@@ -45,5 +45,5 @@
45
45
  "directory": "apps/client/libs/spec-utils",
46
46
  "type": "git"
47
47
  },
48
- "gitHead": "074d65186e102cdf467592eae259a8c9f99e1136"
48
+ "gitHead": "01537987f1d45ce95020236b80582736288d7506"
49
49
  }
@@ -0,0 +1,56 @@
1
+ import { describe, it, expect, assert } from 'vitest';
2
+ import { realpath } from 'node:fs/promises';
3
+ import { getJsExportNames, resolvePath } from '@knapsack/file-utils';
4
+ import { resolveTsModule } from '../resolve.js';
5
+ import { getTsExports } from '../get-exports.js';
6
+ import { paths } from './utils.js';
7
+
8
+ describe.for(paths)(`$path`, ({ path }) => {
9
+ it('resolves to same file path', async () => {
10
+ const { absolutePath } = await resolvePath({
11
+ path,
12
+ resolveType: 'types',
13
+ });
14
+ const { resolvedFileName } = resolveTsModule({
15
+ moduleName: path,
16
+ containingFile: import.meta.filename,
17
+ });
18
+ expect(await realpath(resolvedFileName)).toBe(await realpath(absolutePath));
19
+ });
20
+
21
+ it(
22
+ 'finds same export names in ts and js',
23
+ {
24
+ timeout: 10_000,
25
+ },
26
+ async () => {
27
+ const { exports } = getTsExports({
28
+ fileName: path,
29
+ });
30
+ const exportNamesFromTs = exports.map((e) => e.getName());
31
+
32
+ const { exports: exportNamesFromJs } = await getJsExportNames({
33
+ path,
34
+ });
35
+
36
+ // the ts details will contain things like types that the js details don't
37
+ // this makes sure that all we found in js is also found in ts
38
+ const exportNamesFromJsSet = new Set(exportNamesFromJs);
39
+ exportNamesFromTs.forEach((e) => {
40
+ exportNamesFromJsSet.delete(e);
41
+ });
42
+ if (path === '@mui/material') {
43
+ // pulling these out b/c they fail test, but we got the other ones
44
+ exportNamesFromJsSet.delete('FormLabelRoot');
45
+ exportNamesFromJsSet.delete('private_createMixins');
46
+ exportNamesFromJsSet.delete('usePagination');
47
+ }
48
+ assert.isEmpty(
49
+ exportNamesFromJsSet,
50
+ `found ${exportNamesFromJsSet.size} extra exports in js: ${[
51
+ ...exportNamesFromJsSet,
52
+ ].join(', ')}`,
53
+ );
54
+ },
55
+ );
56
+ });
@@ -0,0 +1,28 @@
1
+ import { bench, describe } from 'vitest';
2
+ import { getJsExportNames } from '@knapsack/file-utils';
3
+ import { getTsExports } from '../get-exports.js';
4
+ import { paths } from './utils.js';
5
+
6
+ paths.forEach(({ path }) => {
7
+ describe(path, () => {
8
+ bench(
9
+ 'getTsExports',
10
+ async () => {
11
+ getTsExports({
12
+ fileName: path,
13
+ });
14
+ },
15
+ {},
16
+ );
17
+
18
+ bench(
19
+ 'getJsExportNames',
20
+ async () => {
21
+ await getJsExportNames({
22
+ path,
23
+ });
24
+ },
25
+ {},
26
+ );
27
+ });
28
+ });
@@ -0,0 +1,20 @@
1
+ import { describe, bench } from 'vitest';
2
+ import { resolvePath } from '@knapsack/file-utils';
3
+ import { resolveTsModule } from '../resolve.js';
4
+ import { paths } from './utils.js';
5
+
6
+ paths.forEach(({ path }) => {
7
+ describe(path, () => {
8
+ bench('resolveTsModule', () => {
9
+ resolveTsModule({
10
+ containingFile: import.meta.filename,
11
+ moduleName: path,
12
+ });
13
+ });
14
+ bench('resolvePath', async () => {
15
+ await resolvePath({
16
+ path,
17
+ });
18
+ });
19
+ });
20
+ });
@@ -0,0 +1,14 @@
1
+ export const paths = [
2
+ {
3
+ path: '@knapsack/sandbox-components/react',
4
+ },
5
+ {
6
+ path: '@knapsack/angular-sandbox-components',
7
+ },
8
+ {
9
+ path: '@mui/material',
10
+ },
11
+ {
12
+ path: '@knapsack/utils',
13
+ },
14
+ ] as const;
@@ -0,0 +1,53 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { analyzeExports } from './analyze-exports.js';
3
+ import { assertTypeInfo } from './utils.js';
4
+
5
+ describe('analyze-exports sandbox components', () => {
6
+ it('analyzes react exports', () => {
7
+ const exports = analyzeExports({
8
+ fileName: '@knapsack/sandbox-components/react',
9
+ });
10
+ const { Button } = exports;
11
+ expect(Button).toBeTruthy();
12
+ assertTypeInfo(Button.typeInfo, 'function');
13
+ const { parameters } = Button.typeInfo;
14
+ const [props] = parameters;
15
+ assertTypeInfo(props.typeInfo, 'object');
16
+ const { properties } = props.typeInfo;
17
+ const { size } = properties;
18
+ assertTypeInfo(size.typeInfo, 'union');
19
+ const { items } = size.typeInfo;
20
+ const sizeValues = items
21
+ .map((item) => {
22
+ assertTypeInfo(item, 'stringLiteral');
23
+ return item.value;
24
+ })
25
+ .sort();
26
+ expect(sizeValues).toEqual(['large', 'medium', 'small'].sort());
27
+ });
28
+
29
+ it('analyzes angular exports', () => {
30
+ const exports = analyzeExports({
31
+ fileName: '@knapsack/angular-sandbox-components',
32
+ });
33
+ const { KsButtonComponent } = exports;
34
+ expect(KsButtonComponent).toBeTruthy();
35
+ assertTypeInfo(KsButtonComponent.typeInfo, 'class');
36
+ const { prototype } = KsButtonComponent.typeInfo;
37
+ assertTypeInfo(prototype.typeInfo, 'object');
38
+ const { hasArrow, click, size, handleClick } =
39
+ prototype.typeInfo.properties;
40
+ assertTypeInfo(hasArrow.typeInfo, 'boolean');
41
+ assertTypeInfo(handleClick.typeInfo, 'function');
42
+ expect(click.typeInfo.tsRawType).toBe('EventEmitter<void>');
43
+ assertTypeInfo(size.typeInfo, 'union');
44
+ const { items } = size.typeInfo;
45
+ const sizeValues = items
46
+ .map((item) => {
47
+ assertTypeInfo(item, 'stringLiteral');
48
+ return item.value;
49
+ })
50
+ .sort();
51
+ expect(sizeValues).toEqual(['large', 'medium', 'small'].sort());
52
+ });
53
+ });
@@ -0,0 +1,54 @@
1
+ import { arrayToDictionary } from '@knapsack/utils';
2
+ import { analyzeSymbol } from './analyze-symbol.js';
3
+ import { getTsExports } from './get-exports.js';
4
+
5
+ export function analyzeExports({
6
+ fileName,
7
+ pkgPathAliases,
8
+ resolveFromDir,
9
+ }: {
10
+ fileName: string;
11
+ pkgPathAliases?: Record<string, string>;
12
+ resolveFromDir?: string;
13
+ }) {
14
+ const { exports, checker } = getTsExports({
15
+ fileName,
16
+ pkgPathAliases,
17
+ resolveFromDir,
18
+ });
19
+ return arrayToDictionary(
20
+ exports.map((symbol) =>
21
+ analyzeSymbol({
22
+ symbol,
23
+ checker,
24
+ }),
25
+ ),
26
+ 'name',
27
+ );
28
+ }
29
+
30
+ export function analyzeExport({
31
+ fileName,
32
+ exportName,
33
+ pkgPathAliases,
34
+ resolveFromDir,
35
+ }: {
36
+ fileName: string;
37
+ exportName: string;
38
+ pkgPathAliases?: Record<string, string>;
39
+ resolveFromDir?: string;
40
+ }) {
41
+ const { exports, checker } = getTsExports({
42
+ fileName,
43
+ pkgPathAliases,
44
+ resolveFromDir,
45
+ });
46
+ const theExport = exports.find((e) => e.getName() === exportName);
47
+ if (!theExport) {
48
+ throw new Error(`Export ${exportName} not found in ${fileName}`);
49
+ }
50
+ return analyzeSymbol({
51
+ symbol: theExport,
52
+ checker,
53
+ });
54
+ }
@@ -0,0 +1,178 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { join } from 'node:path';
3
+ import { analyzeExports } from './analyze-exports.js';
4
+ import { assertTypeInfo } from './utils.js';
5
+
6
+ const tsDetailsSrc = join(import.meta.dirname, '../src/test-fixtures/index.ts');
7
+ const tsDetailsDts = join(
8
+ import.meta.dirname,
9
+ '../dist/test-fixtures/index.d.ts',
10
+ );
11
+
12
+ [tsDetailsSrc, tsDetailsDts].forEach((fileName) => {
13
+ const ext = fileName.endsWith('.d.ts') ? '.d.ts' : '.ts';
14
+ const exports = analyzeExports({ fileName });
15
+
16
+ describe(`analyze-exports tests for ${ext} files`, () => {
17
+ it(`gets export names`, () => {
18
+ const results = analyzeExports({
19
+ fileName,
20
+ });
21
+ const exportNames = Object.keys(results);
22
+ expect(exportNames).toContain('complexFuncTypes');
23
+ expect(exportNames).toContain('doIt');
24
+ });
25
+
26
+ it(`handles basics: number`, () => {
27
+ const { typeInfo } = exports.aNumber;
28
+ expect(typeInfo.type).toBe('number');
29
+ });
30
+
31
+ it(`handles string union`, () => {
32
+ const { typeInfo } = exports.stringUnion;
33
+ assertTypeInfo(typeInfo, 'union');
34
+ const { items } = typeInfo;
35
+ const sizes = items.map((item) => {
36
+ if (item.type !== 'stringLiteral') {
37
+ throw new Error(
38
+ `Expected type to be stringLiteral, got ${item.type}`,
39
+ );
40
+ }
41
+ return item.value;
42
+ });
43
+ expect(sizes).toEqual(['small', 'medium', 'large']);
44
+ });
45
+
46
+ it(`handles string via type alias`, () => {
47
+ const { typeInfo } = exports.stringViaTypeAlias;
48
+ expect(typeInfo.type).toBe('string');
49
+ });
50
+
51
+ it(`handles jsdoc`, () => {
52
+ const { jsDoc } = exports.complexFuncTypes;
53
+ if (!jsDoc) {
54
+ throw new Error('jsDoc is undefined');
55
+ }
56
+ expect(jsDoc.description).toBe('Some basic types');
57
+ expect(jsDoc.jsDocTags.length).toBe(1);
58
+ expect(jsDoc.jsDocTags).toEqual([
59
+ { name: 'link', text: 'https://www.example.com' },
60
+ ] satisfies typeof jsDoc.jsDocTags);
61
+ });
62
+
63
+ it(`handles basics: string[]`, () => {
64
+ const { typeInfo } = exports.anArrayOfStrings;
65
+ assertTypeInfo(typeInfo, 'array');
66
+ expect(typeInfo.items.type).toBe('string');
67
+ expect(typeInfo.tsRawType).toBe('string[]');
68
+ });
69
+
70
+ it(`handles basics: object`, () => {
71
+ const { typeInfo } = exports.anObject;
72
+ assertTypeInfo(typeInfo, 'object');
73
+ const {
74
+ properties: { a, b, c },
75
+ } = typeInfo;
76
+ expect(a.typeInfo.type).toBe('number');
77
+ expect(b.typeInfo.type).toBe('string');
78
+ assertTypeInfo(c.typeInfo, 'array');
79
+ expect(c.typeInfo.items.type).toBe('string');
80
+ expect(c.typeInfo.tsRawType).toBe('string[]');
81
+ });
82
+
83
+ it(`handles function with basic parameters`, () => {
84
+ const { typeInfo } = exports.aFunction;
85
+ assertTypeInfo(typeInfo, 'function');
86
+ const { parameters, returnType, tsRawType } = typeInfo;
87
+ if (!returnType) {
88
+ throw new Error('returnType is undefined');
89
+ }
90
+ const [param] = parameters;
91
+ expect(tsRawType).toBe('(a: number) => number');
92
+ expect(param.name).toBe('a');
93
+ expect(param.typeInfo.type).toBe('number');
94
+ expect(returnType.type).toBe('number');
95
+ });
96
+
97
+ it(`handles async function with basic parameters`, () => {
98
+ const { typeInfo } = exports.asyncFunction;
99
+ assertTypeInfo(typeInfo, 'function');
100
+ const { parameters, returnType, tsRawType } = typeInfo;
101
+ if (!returnType) {
102
+ throw new Error('returnType is undefined');
103
+ }
104
+ const [param] = parameters;
105
+ expect(param.name).toBe('a');
106
+ expect(param.typeInfo.type).toBe('number');
107
+ expect(tsRawType).toBe('(a: number) => Promise<number>');
108
+ expect(returnType.type).toBe('misc');
109
+ });
110
+
111
+ it(`handles function with complex parameters`, () => {
112
+ const { typeInfo } = exports.complexFuncTypes;
113
+ assertTypeInfo(typeInfo, 'function');
114
+ const [param] = typeInfo.parameters;
115
+ expect(param.name).toBe('obj');
116
+ assertTypeInfo(param.typeInfo, 'object');
117
+ const { properties } = param.typeInfo;
118
+ Object.entries(properties).forEach(([key, { typeInfo: propInfo }]) => {
119
+ switch (key) {
120
+ case 'aString': {
121
+ expect(propInfo.type).toBe('string');
122
+ expect(propInfo.isOptional).toBe(false);
123
+ break;
124
+ }
125
+ case 'anOptionalString': {
126
+ expect(propInfo.type).toBe('string');
127
+ expect(propInfo.isOptional).toBe(true);
128
+ break;
129
+ }
130
+ case 'aBoolean': {
131
+ expect(propInfo.type).toBe('boolean');
132
+ expect(propInfo.isOptional).toBe(false);
133
+ break;
134
+ }
135
+ case 'someSizes': {
136
+ assertTypeInfo(propInfo, 'union');
137
+ const sizes = propInfo.items.map((item) => {
138
+ assertTypeInfo(item, 'stringLiteral');
139
+ return item.value;
140
+ });
141
+ expect(sizes).toEqual(['small', 'medium', 'large']);
142
+ break;
143
+ }
144
+ case 'anArray': {
145
+ assertTypeInfo(propInfo, 'array');
146
+ expect(propInfo.items.type).toBe('string');
147
+ break;
148
+ }
149
+ case 'aFunc': {
150
+ assertTypeInfo(propInfo, 'function');
151
+ const { parameters, returnType } = propInfo;
152
+ if (!returnType) {
153
+ throw new Error('returnType is undefined');
154
+ }
155
+ const [p] = parameters;
156
+ expect(p.name).toBe('a');
157
+ expect(p.typeInfo.type).toBe('string');
158
+ expect(returnType.type).toBe('string');
159
+ break;
160
+ }
161
+ case 'anotherFunc': {
162
+ assertTypeInfo(propInfo, 'function');
163
+ const { parameters } = propInfo;
164
+ const [p] = parameters;
165
+ expect(p.name).toBe('opt');
166
+ assertTypeInfo(p.typeInfo, 'object');
167
+ const { onFoo } = p.typeInfo.properties;
168
+ assertTypeInfo(onFoo.typeInfo, 'function');
169
+ const [onFooParam] = onFoo.typeInfo.parameters;
170
+ expect(onFooParam.name).toBe('a');
171
+ expect(onFooParam.typeInfo.type).toBe('string');
172
+ break;
173
+ }
174
+ }
175
+ });
176
+ });
177
+ });
178
+ });