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