1import { render } from '@testing-library/react';
2import * as React from 'react';
3
4import { CommentTextBlock, mdInlineComponents, resolveTypeName } from './APISectionUtils';
5
6describe('APISectionUtils.resolveTypeName', () => {
7  test('void', () => {
8    const { container } = render(<>{resolveTypeName({ type: 'intrinsic', name: 'void' })}</>);
9    expect(container).toMatchSnapshot();
10  });
11
12  test('generic type', () => {
13    const { container } = render(<>{resolveTypeName({ type: 'intrinsic', name: 'string' })}</>);
14    expect(container).toMatchSnapshot();
15  });
16
17  test('custom type', () => {
18    const { container } = render(
19      <>{resolveTypeName({ type: 'reference', name: 'SpeechSynthesisEvent' })}</>
20    );
21    expect(container).toMatchSnapshot();
22  });
23
24  test('custom type array', () => {
25    const { container } = render(
26      <>
27        {resolveTypeName({
28          type: 'array',
29          elementType: { type: 'reference', name: 'AppleAuthenticationScope' },
30        })}
31      </>
32    );
33    expect(container).toMatchSnapshot();
34  });
35
36  test('custom type non-linkable array', () => {
37    const { container } = render(
38      <>
39        {resolveTypeName({
40          type: 'array',
41          elementType: { type: 'reference', name: 'T' },
42        })}
43      </>
44    );
45    expect(container).toMatchSnapshot();
46  });
47
48  test('query type', () => {
49    const { container } = render(
50      <>
51        {resolveTypeName({
52          type: 'reference',
53          typeArguments: [{ queryType: { type: 'reference', name: 'View' }, type: 'query' }],
54          name: 'React.ComponentProps',
55        })}
56      </>
57    );
58    expect(container).toMatchSnapshot();
59  });
60
61  test('Promise', () => {
62    const { container } = render(
63      <>
64        {resolveTypeName({
65          type: 'reference',
66          typeArguments: [{ type: 'intrinsic', name: 'void' }],
67          name: 'Promise',
68        })}
69      </>
70    );
71    expect(container).toMatchSnapshot();
72  });
73
74  test('Promise with custom type', () => {
75    const { container } = render(
76      <>
77        {resolveTypeName({
78          type: 'reference',
79          typeArguments: [{ type: 'reference', name: 'AppleAuthenticationCredential' }],
80          name: 'Promise',
81        })}
82      </>
83    );
84    expect(container).toMatchSnapshot();
85  });
86
87  test('Record', () => {
88    const { container } = render(
89      <>
90        {resolveTypeName({
91          type: 'reference',
92          typeArguments: [
93            { type: 'intrinsic', name: 'string' },
94            { type: 'intrinsic', name: 'any' },
95          ],
96          name: 'Record',
97        })}
98      </>
99    );
100    expect(container).toMatchSnapshot();
101  });
102
103  test('alternative generic object notation', () => {
104    const { container } = render(
105      <>
106        {resolveTypeName({
107          type: 'array',
108          elementType: {
109            type: 'reflection',
110            declaration: {
111              name: '__type',
112              indexSignature: {
113                name: '__index',
114                parameters: [{ name: 'column', type: { type: 'intrinsic', name: 'string' } }],
115                type: { type: 'intrinsic', name: 'any' },
116              },
117            },
118          },
119        })}
120      </>
121    );
122    expect(container).toMatchSnapshot();
123  });
124
125  test('Record with union', () => {
126    const { container } = render(
127      <>
128        {resolveTypeName({
129          type: 'reference',
130          typeArguments: [
131            { type: 'intrinsic', name: 'string' },
132            {
133              type: 'union',
134              types: [
135                { type: 'intrinsic', name: 'number' },
136                { type: 'intrinsic', name: 'boolean' },
137                { type: 'intrinsic', name: 'string' },
138              ],
139            },
140          ],
141          name: 'Record',
142        })}
143      </>
144    );
145    expect(container).toMatchSnapshot();
146  });
147
148  test('union', () => {
149    const { container } = render(
150      <>
151        {resolveTypeName({
152          type: 'union',
153          types: [
154            { type: 'reference', name: 'SpeechEventCallback' },
155            { type: 'literal', value: null },
156          ],
157        })}
158      </>
159    );
160    expect(container).toMatchSnapshot();
161  });
162
163  test('union with array', () => {
164    const { container } = render(
165      <>
166        {resolveTypeName({
167          type: 'union',
168          types: [
169            { type: 'array', elementType: { type: 'intrinsic', name: 'number' } },
170            { type: 'literal', value: null },
171          ],
172        })}
173      </>
174    );
175    expect(container).toMatchSnapshot();
176  });
177
178  test('union with custom type and array', () => {
179    const { container } = render(
180      <>
181        {resolveTypeName({
182          type: 'union',
183          types: [
184            { type: 'array', elementType: { type: 'reference', name: 'AssetRef' } },
185            { type: 'reference', name: 'AssetRef' },
186          ],
187        })}
188      </>
189    );
190    expect(container).toMatchSnapshot();
191  });
192
193  test('union of array values', () => {
194    const { container } = render(
195      <>
196        {resolveTypeName({
197          type: 'array',
198          elementType: {
199            type: 'union',
200            types: [
201              { type: 'reference', name: 'ResultSetError' },
202              { type: 'reference', name: 'ResultSet' },
203            ],
204          },
205        })}
206      </>
207    );
208    expect(container).toMatchSnapshot();
209  });
210
211  test('generic type', () => {
212    const { container } = render(
213      <>
214        {resolveTypeName({
215          type: 'reference',
216          typeArguments: [{ type: 'reference', name: 'Asset' }],
217          name: 'PagedInfo',
218        })}
219      </>
220    );
221    expect(container).toMatchSnapshot();
222  });
223
224  test('tuple type', () => {
225    const { container } = render(
226      <>
227        {resolveTypeName({
228          type: 'tuple',
229          elements: [
230            { type: 'reference', name: 'SortByKey' },
231            { type: 'intrinsic', name: 'boolean' },
232          ],
233        })}
234      </>
235    );
236    expect(container).toMatchSnapshot();
237  });
238
239  test('generic type in Promise', () => {
240    const { container } = render(
241      <>
242        {resolveTypeName({
243          type: 'reference',
244          typeArguments: [
245            {
246              type: 'reference',
247              typeArguments: [{ type: 'reference', name: 'Asset' }],
248              name: 'PagedInfo',
249            },
250          ],
251          name: 'Promise',
252        })}
253      </>
254    );
255    expect(container).toMatchSnapshot();
256  });
257
258  test('function', () => {
259    const { container } = render(
260      <>
261        {resolveTypeName({
262          type: 'reflection',
263          declaration: {
264            signatures: [
265              {
266                type: {
267                  type: 'union',
268                  types: [
269                    { type: 'intrinsic', name: 'void' },
270                    {
271                      type: 'reference',
272                      name: 'SpeechEventCallback',
273                    },
274                  ],
275                },
276              },
277            ],
278          },
279        })}
280      </>
281    );
282    expect(container).toMatchSnapshot();
283  });
284
285  test('function with arguments', () => {
286    const { container } = render(
287      <>
288        {resolveTypeName({
289          type: 'reflection',
290          declaration: {
291            signatures: [
292              {
293                parameters: [
294                  {
295                    name: 'error',
296                    type: { type: 'reference', name: 'Error' },
297                  },
298                ],
299                type: {
300                  type: 'union',
301                  types: [
302                    { type: 'intrinsic', name: 'void' },
303                    { type: 'reference', name: 'SpeechEventCallback' },
304                  ],
305                },
306              },
307            ],
308          },
309        })}
310      </>
311    );
312    expect(container).toMatchSnapshot();
313  });
314
315  test('function with non-linkable custom type', () => {
316    const { container } = render(
317      <>
318        {resolveTypeName({
319          type: 'reflection',
320          declaration: {
321            signatures: [
322              {
323                parameters: [
324                  {
325                    name: 'error',
326                    type: { type: 'reference', name: 'Error' },
327                  },
328                ],
329                type: { type: 'intrinsic', name: 'void' },
330              },
331            ],
332          },
333        })}
334      </>
335    );
336    expect(container).toMatchSnapshot();
337  });
338
339  test('object reflection', () => {
340    const { container } = render(
341      <>
342        {resolveTypeName({
343          type: 'reflection',
344          declaration: {
345            children: [
346              {
347                name: 'target',
348                type: { type: 'intrinsic', name: 'number' },
349              },
350              {
351                name: 'value',
352                type: { type: 'intrinsic', name: 'boolean' },
353              },
354            ],
355          },
356        })}
357      </>
358    );
359    expect(container).toMatchSnapshot();
360  });
361
362  test('custom type with single pick', () => {
363    const { container } = render(
364      <>
365        {resolveTypeName({
366          type: 'reference',
367          typeArguments: [
368            { type: 'reference', name: 'FontResource' },
369            { type: 'literal', value: 'display' },
370          ],
371          name: 'Pick',
372        })}
373      </>
374    );
375    expect(container).toMatchSnapshot();
376  });
377
378  test('props with multiple omits', () => {
379    const { container } = render(
380      <>
381        {resolveTypeName({
382          type: 'reference',
383          typeArguments: [
384            {
385              type: 'reference',
386              typeArguments: [
387                { type: 'reference', name: 'ViewStyle' },
388                {
389                  type: 'union',
390                  types: [
391                    { type: 'literal', value: 'backgroundColor' },
392                    {
393                      type: 'literal',
394                      value: 'borderRadius',
395                    },
396                  ],
397                },
398              ],
399              name: 'Omit',
400            },
401          ],
402          name: 'StyleProp',
403        })}
404      </>
405    );
406    expect(container).toMatchSnapshot();
407  });
408});
409
410describe('APISectionUtils.CommentTextBlock component', () => {
411  test('no comment', () => {
412    const { container } = render(<CommentTextBlock comment={undefined} />);
413    expect(container).toMatchSnapshot();
414  });
415
416  test('basic comment', () => {
417    const comment = {
418      text: 'This is the basic comment.',
419    };
420
421    const { container } = render(<CommentTextBlock comment={comment} />);
422    expect(container).toMatchSnapshot();
423  });
424
425  test('basic inline comment', () => {
426    const comment = {
427      shortText: 'This is the basic comment.',
428    };
429
430    const { container } = render(
431      <CommentTextBlock comment={comment} components={mdInlineComponents} withDash />
432    );
433    expect(container).toMatchSnapshot();
434  });
435
436  test('comment with example', () => {
437    const comment = {
438      shortText:
439        '**Android only.** Gets the referrer URL of the installed app with the [`Install Referrer API`](https://developer.android.com/google/play/installreferrer)\nfrom the Google Play Store. In practice, the referrer URL may not be a complete, absolute URL.',
440      tags: [
441        {
442          tag: 'example',
443          text: '\n```ts\nawait Application.getInstallReferrerAsync();\n// "utm_source=google-play&utm_medium=organic"\n```\n',
444        },
445      ],
446    };
447
448    const { container } = render(<CommentTextBlock comment={comment} />);
449    expect(container).toMatchSnapshot();
450  });
451});
452