@xlr-lib/xlr-converters 0.1.1-next.0

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.
@@ -0,0 +1,776 @@
1
+ import { test, expect, describe, vi } from "vitest";
2
+ import { setupTestEnv } from "@xlr-lib/test-utils";
3
+ import { TsConverter } from "..";
4
+
5
+ describe("Type Exports", () => {
6
+ vi.setConfig({
7
+ testTimeout: 2 * 60 * 10000,
8
+ });
9
+
10
+ test("Basic Array Type", () => {
11
+ const sc = `
12
+ export type Foo = Array<string>
13
+ `;
14
+
15
+ const { sf, tc } = setupTestEnv(sc);
16
+ const converter = new TsConverter(tc);
17
+ const XLR = converter.convertSourceFile(sf).data.types;
18
+
19
+ expect(XLR).toMatchSnapshot();
20
+ });
21
+
22
+ test("Basic Union Type", () => {
23
+ const sc = `
24
+ export type Foo = number | string
25
+ `;
26
+
27
+ const { sf, tc } = setupTestEnv(sc);
28
+ const converter = new TsConverter(tc);
29
+ const XLR = converter.convertSourceFile(sf).data.types;
30
+
31
+ expect(XLR).toMatchSnapshot();
32
+ });
33
+ });
34
+
35
+ describe("Interface Exports", () => {
36
+ test("Basic Interface Type", () => {
37
+ const sc = `
38
+ export interface Foo {
39
+ bar: string
40
+ bax: number
41
+ }
42
+ `;
43
+
44
+ const { sf, tc } = setupTestEnv(sc);
45
+ const converter = new TsConverter(tc);
46
+ const XLR = converter.convertSourceFile(sf).data.types;
47
+
48
+ expect(XLR).toMatchSnapshot();
49
+ });
50
+
51
+ test("Interface with Optional parameters", () => {
52
+ const sc = `
53
+ export interface Foo {
54
+ bar: string
55
+ bax?: number
56
+ }
57
+ `;
58
+
59
+ const { sf, tc } = setupTestEnv(sc);
60
+ const converter = new TsConverter(tc);
61
+ const XLR = converter.convertSourceFile(sf).data.types;
62
+
63
+ expect(XLR).toMatchSnapshot();
64
+ });
65
+
66
+ test("Interface with Inheritance", () => {
67
+ const sc = `
68
+
69
+ interface Base {
70
+ baw: any
71
+ }
72
+
73
+ export interface Foo extends Base {
74
+ bar: string
75
+ bax?: number
76
+ }
77
+ `;
78
+
79
+ const { sf, tc } = setupTestEnv(sc);
80
+ const converter = new TsConverter(tc);
81
+ const XLR = converter.convertSourceFile(sf).data.types;
82
+
83
+ expect(XLR).toMatchSnapshot();
84
+ });
85
+
86
+ test("Implementing more than one Interfaces", () => {
87
+ const sc = `
88
+
89
+ interface Foo{
90
+ foo: number
91
+ }
92
+
93
+ interface Bar{
94
+ bar: string
95
+ }
96
+
97
+ export interface Test extends Foo, Bar {
98
+ test: any
99
+ }
100
+
101
+ `;
102
+
103
+ const { sf, tc } = setupTestEnv(sc);
104
+ const converter = new TsConverter(tc);
105
+ const XLR = converter.convertSourceFile(sf).data.types;
106
+
107
+ expect(XLR).toMatchSnapshot();
108
+ });
109
+ });
110
+
111
+ describe("Generic Declarations", () => {
112
+ test("Basic Generic Type", () => {
113
+ const sc = `
114
+ export type Foo<T> = string | T
115
+ `;
116
+
117
+ const { sf, tc } = setupTestEnv(sc);
118
+ const converter = new TsConverter(tc);
119
+ const XLR = converter.convertSourceFile(sf).data.types;
120
+
121
+ expect(XLR).toMatchSnapshot();
122
+ });
123
+
124
+ test("Generic with Constraints", () => {
125
+ const sc = `
126
+ export type Foo<T extends string = string > = number | T
127
+ `;
128
+
129
+ const { sf, tc } = setupTestEnv(sc);
130
+ const converter = new TsConverter(tc);
131
+ const XLR = converter.convertSourceFile(sf).data.types;
132
+
133
+ expect(XLR).toMatchSnapshot();
134
+ });
135
+
136
+ test("Implementing Generic Type", () => {
137
+ const sc = `
138
+ type Foo<T> = string | T
139
+
140
+ export type Bar = boolean | Foo<number>
141
+ `;
142
+
143
+ const { sf, tc } = setupTestEnv(sc);
144
+ const converter = new TsConverter(tc);
145
+ const XLR = converter.convertSourceFile(sf).data.types;
146
+
147
+ expect(XLR).toMatchSnapshot();
148
+ });
149
+
150
+ test("Interface with Generics", () => {
151
+ const sc = `
152
+
153
+ export interface Foo<T>{
154
+ bar: T
155
+ }
156
+ `;
157
+
158
+ const { sf, tc } = setupTestEnv(sc);
159
+ const converter = new TsConverter(tc);
160
+ const XLR = converter.convertSourceFile(sf).data.types;
161
+
162
+ expect(XLR).toMatchSnapshot();
163
+ });
164
+
165
+ test("Interface with Generics and Constraints", () => {
166
+ const sc = `
167
+
168
+ export interface Foo<T extends string = string>{
169
+ bar: T
170
+ }
171
+ `;
172
+
173
+ const { sf, tc } = setupTestEnv(sc);
174
+ const converter = new TsConverter(tc);
175
+ const XLR = converter.convertSourceFile(sf).data.types;
176
+
177
+ expect(XLR).toMatchSnapshot();
178
+ });
179
+
180
+ test("Implementing Interface with Generics", () => {
181
+ const sc = `
182
+
183
+ interface Base<T extends string = string>{
184
+ bar: T
185
+ }
186
+
187
+ interface Foo extends Bar<"test"> {
188
+ bam: number
189
+ }
190
+
191
+ `;
192
+
193
+ const { sf, tc } = setupTestEnv(sc);
194
+ const converter = new TsConverter(tc);
195
+ const XLR = converter.convertSourceFile(sf).data.types;
196
+
197
+ expect(XLR).toMatchSnapshot();
198
+ });
199
+
200
+ test("Implementing an generic wrapped interface", () => {
201
+ const sc = `
202
+
203
+ interface base {
204
+ foo: number
205
+ bar: string
206
+ }
207
+
208
+ export interface Test extends Pick<base,"bar"> {
209
+ test: any
210
+ }
211
+
212
+ `;
213
+
214
+ const { sf, tc } = setupTestEnv(sc);
215
+ const converter = new TsConverter(tc);
216
+ const XLR = converter.convertSourceFile(sf).data.types;
217
+
218
+ expect(XLR).toMatchSnapshot();
219
+ });
220
+ });
221
+
222
+ describe("Complex Types", () => {
223
+ test("Pick", () => {
224
+ const sc = `
225
+ interface foo {
226
+ bar: string
227
+ bax: number
228
+ }
229
+ export type Bar = Pick<foo,"bar">
230
+ `;
231
+
232
+ const { sf, tc } = setupTestEnv(sc);
233
+ const converter = new TsConverter(tc);
234
+ const XLR = converter.convertSourceFile(sf).data.types;
235
+
236
+ expect(XLR).toMatchSnapshot();
237
+ });
238
+
239
+ test("Pick with interface union", () => {
240
+ const sc = `
241
+ interface foo {
242
+ far: string
243
+ fax: number
244
+ }
245
+
246
+ interface boo {
247
+ far: number,
248
+ bax: boolean
249
+ }
250
+
251
+ type test = foo | boo
252
+
253
+ export type Bar = Pick<test,"far">
254
+ `;
255
+
256
+ const { sf, tc } = setupTestEnv(sc);
257
+ const converter = new TsConverter(tc);
258
+ const XLR = converter.convertSourceFile(sf).data.types;
259
+
260
+ expect(XLR).toMatchSnapshot();
261
+ });
262
+
263
+ test("Pick with interface intersection", () => {
264
+ const sc = `
265
+ interface foo {
266
+ far: string
267
+ fax: number
268
+ }
269
+
270
+ interface boo {
271
+ far: string,
272
+ bax: boolean
273
+ }
274
+
275
+ type test = foo | boo
276
+
277
+ export type Bar = Pick<test,"far">
278
+ `;
279
+
280
+ const { sf, tc } = setupTestEnv(sc);
281
+ const converter = new TsConverter(tc);
282
+ const XLR = converter.convertSourceFile(sf).data.types;
283
+
284
+ expect(XLR).toMatchSnapshot();
285
+ });
286
+
287
+ test("Omit", () => {
288
+ const sc = `
289
+ interface foo {
290
+ bar: string
291
+ bax: number
292
+ }
293
+ export type Bar = Omit<foo,"bar">
294
+ `;
295
+
296
+ const { sf, tc } = setupTestEnv(sc);
297
+ const converter = new TsConverter(tc);
298
+ const XLR = converter.convertSourceFile(sf).data.types;
299
+
300
+ expect(XLR).toMatchSnapshot();
301
+ });
302
+
303
+ test("Omit with type union", () => {
304
+ const sc = `
305
+ interface foo {
306
+ far: string
307
+ fax: number
308
+ }
309
+
310
+ interface boo {
311
+ far: string,
312
+ bax: boolean
313
+ }
314
+
315
+ type test = foo | boo
316
+
317
+ export type Bar = Omit<test,"bax">
318
+ `;
319
+
320
+ const { sf, tc } = setupTestEnv(sc);
321
+ const converter = new TsConverter(tc);
322
+ const XLR = converter.convertSourceFile(sf).data.types;
323
+
324
+ expect(XLR).toMatchSnapshot();
325
+ });
326
+
327
+ test("Omit with type intersection", () => {
328
+ const sc = `
329
+ interface foo {
330
+ far: string
331
+ fax: number
332
+ }
333
+
334
+ interface boo {
335
+ far: string,
336
+ bax: boolean
337
+ }
338
+
339
+ type test = foo & boo
340
+
341
+ export type Bar = Omit<test,"far">
342
+ `;
343
+
344
+ const { sf, tc } = setupTestEnv(sc);
345
+ const converter = new TsConverter(tc);
346
+ const XLR = converter.convertSourceFile(sf).data.types;
347
+
348
+ expect(XLR).toMatchSnapshot();
349
+ });
350
+
351
+ test("Exclude with primitives", () => {
352
+ const sc = `
353
+ const foo = ['a', 'b', 'c'] as const;
354
+
355
+ type fooType = typeof foo[number];
356
+
357
+ export type bar = Exclude<fooType, 'a'>;
358
+ `;
359
+
360
+ const { sf, tc } = setupTestEnv(sc);
361
+ const converter = new TsConverter(tc);
362
+ const XLR = converter.convertSourceFile(sf).data.types;
363
+
364
+ expect(XLR).toMatchSnapshot();
365
+ });
366
+
367
+ test("Exclude with objects", () => {
368
+ const sc = `
369
+ type foo = { type: 'a'; value: string } | { type: 'b'; value: number } | { type: 'c'; value: boolean };
370
+
371
+ export type bar = Exclude<foo, { type: 'a' }>;
372
+ `;
373
+
374
+ const { sf, tc } = setupTestEnv(sc);
375
+ const converter = new TsConverter(tc);
376
+ const XLR = converter.convertSourceFile(sf).data.types;
377
+
378
+ expect(XLR).toMatchSnapshot();
379
+ });
380
+
381
+ test("Exclude with objects collapses single remaining element", () => {
382
+ const sc = `
383
+ type foo = { type: 'a'; value: string } | { type: 'b'; value: number };
384
+
385
+ export type bar = Exclude<foo, { type: 'a' }>;
386
+ `;
387
+
388
+ const { sf, tc } = setupTestEnv(sc);
389
+ const converter = new TsConverter(tc);
390
+ const XLR = converter.convertSourceFile(sf).data.types;
391
+
392
+ expect(XLR).toMatchSnapshot();
393
+ });
394
+ });
395
+
396
+ describe("String Templates", () => {
397
+ test("Basic", () => {
398
+ const sc =
399
+ "export type Bar = `String is a ${string}, number is a ${number} and boolean is a ${boolean}`";
400
+
401
+ const { sf, tc } = setupTestEnv(sc);
402
+ const converter = new TsConverter(tc);
403
+ const XLR = converter.convertSourceFile(sf).data.types;
404
+
405
+ expect(XLR).toMatchSnapshot();
406
+ });
407
+
408
+ test("Type References", () => {
409
+ const sc =
410
+ "type Foo = string; export type Bar = `String is a ${Foo}, number is a ${number} and boolean is a ${boolean}`";
411
+
412
+ const { sf, tc } = setupTestEnv(sc);
413
+ const converter = new TsConverter(tc);
414
+ const XLR = converter.convertSourceFile(sf).data.types;
415
+
416
+ expect(XLR).toMatchSnapshot();
417
+ });
418
+ });
419
+
420
+ describe("Index Types", () => {
421
+ test("Basic", () => {
422
+ const sc = `
423
+ interface base {
424
+ foo: string;
425
+ bar: number;
426
+ }
427
+
428
+ export interface test {
429
+ key: base["foo"];
430
+ key2: base['bar'];
431
+ }
432
+
433
+ `;
434
+
435
+ const { sf, tc } = setupTestEnv(sc);
436
+ const converter = new TsConverter(tc);
437
+ const XLR = converter.convertSourceFile(sf).data.types;
438
+
439
+ expect(XLR).toMatchSnapshot();
440
+ });
441
+
442
+ test("Complex Types", () => {
443
+ const sc = `
444
+
445
+ interface something {
446
+ prop1: string;
447
+ prop2: number
448
+ }
449
+
450
+ interface base {
451
+ foo: something;
452
+ bar: number;
453
+ }
454
+
455
+ export interface test {
456
+ key: base["foo"]
457
+ }
458
+
459
+ `;
460
+
461
+ const { sf, tc } = setupTestEnv(sc);
462
+ const converter = new TsConverter(tc);
463
+ const XLR = converter.convertSourceFile(sf).data.types;
464
+
465
+ expect(XLR).toMatchSnapshot();
466
+ });
467
+ });
468
+
469
+ describe("Type with typeof", () => {
470
+ test("Indexing", () => {
471
+ const sc = `
472
+ const options = [
473
+ "one",
474
+ "two",
475
+ "three"
476
+ ] as const
477
+
478
+ export type options = typeof options[number];
479
+ export type options2 = (typeof options)[number];
480
+ `;
481
+
482
+ const { sf, tc } = setupTestEnv(sc);
483
+ const converter = new TsConverter(tc);
484
+ const XLR = converter.convertSourceFile(sf).data.types;
485
+
486
+ expect(XLR).toMatchSnapshot();
487
+ });
488
+
489
+ test("Indexing (long)", () => {
490
+ const sc = `
491
+ const options = [
492
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
493
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
494
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
495
+ ] as const;
496
+
497
+ export type options = typeof options[number];
498
+
499
+ `;
500
+
501
+ const { sf, tc } = setupTestEnv(sc);
502
+ const converter = new TsConverter(tc);
503
+ const XLR = converter.convertSourceFile(sf).data.types;
504
+
505
+ expect(XLR).toMatchSnapshot();
506
+ });
507
+ });
508
+
509
+ describe("Edge Cases", () => {
510
+ test("Modifying Cache References", () => {
511
+ const sc = `
512
+ interface foo {
513
+ foo: string;
514
+ }
515
+
516
+ interface bar {
517
+ bar: number;
518
+ }
519
+
520
+ type types = foo | bar;
521
+
522
+ type requiredTypes = types & {
523
+ baz: number;
524
+ };
525
+
526
+ export type test = requiredTypes & Partial<Pick<requiredTypes, "baz">>;
527
+
528
+ `;
529
+
530
+ const { sf, tc } = setupTestEnv(sc);
531
+ const converter = new TsConverter(tc);
532
+ const XLR = converter.convertSourceFile(sf).data.types;
533
+
534
+ expect(XLR).toMatchSnapshot();
535
+ });
536
+ });
537
+
538
+ describe("Variable Exports", () => {
539
+ test("Primitive const exports", () => {
540
+ const sc = `
541
+ export const foo = 1;
542
+
543
+ export const bar = "test";
544
+
545
+ export const far = true;
546
+ `;
547
+
548
+ const { sf, tc } = setupTestEnv(sc);
549
+ const converter = new TsConverter(tc);
550
+ const XLR = converter.convertSourceFile(sf).data.types;
551
+
552
+ expect(XLR).toMatchSnapshot();
553
+ });
554
+
555
+ test("Object const exports", () => {
556
+ const sc = `
557
+ export const foo = {
558
+ foo: 1,
559
+ bar: "test",
560
+ far: false
561
+ }
562
+ `;
563
+
564
+ const { sf, tc } = setupTestEnv(sc);
565
+ const converter = new TsConverter(tc);
566
+ const XLR = converter.convertSourceFile(sf).data.types;
567
+
568
+ expect(XLR).toMatchSnapshot();
569
+ });
570
+
571
+ test("Object const exports with spread", () => {
572
+ const sc = `
573
+ const foo = {
574
+ foo: 1,
575
+ bar: "test",
576
+ far: false
577
+ }
578
+
579
+ export const far = {
580
+ ...foo,
581
+ mar: 2
582
+ }
583
+ `;
584
+
585
+ const { sf, tc } = setupTestEnv(sc);
586
+ const converter = new TsConverter(tc);
587
+ const XLR = converter.convertSourceFile(sf).data.types;
588
+
589
+ expect(XLR).toMatchSnapshot();
590
+ });
591
+
592
+ test("Array const exports", () => {
593
+ const sc = `
594
+ export const foo = [1,2,3]
595
+ `;
596
+
597
+ const { sf, tc } = setupTestEnv(sc);
598
+ const converter = new TsConverter(tc);
599
+ const XLR = converter.convertSourceFile(sf).data.types;
600
+
601
+ expect(XLR).toMatchSnapshot();
602
+ });
603
+
604
+ test("Array const exports with spread", () => {
605
+ const sc = `
606
+ const foo = [1,2,3]
607
+ export const bar = [...foo, 4]
608
+ `;
609
+
610
+ const { sf, tc } = setupTestEnv(sc);
611
+ const converter = new TsConverter(tc);
612
+ const XLR = converter.convertSourceFile(sf).data.types;
613
+
614
+ expect(XLR).toMatchSnapshot();
615
+ });
616
+
617
+ test("Function with primitive return type", () => {
618
+ const sc = `
619
+ function test(arg1: string): string {
620
+ return ""
621
+ }
622
+
623
+ export const foo = test("1")
624
+ `;
625
+
626
+ const { sf, tc } = setupTestEnv(sc);
627
+ const converter = new TsConverter(tc);
628
+ const XLR = converter.convertSourceFile(sf).data.types;
629
+
630
+ expect(XLR).toMatchSnapshot();
631
+ });
632
+
633
+ test("Function with object return type", () => {
634
+ const sc = `
635
+ interface Bar {
636
+ foo: string
637
+ fuz: number
638
+ }
639
+
640
+ function test(arg1: string): Bar {
641
+ return {
642
+ foo: "1",
643
+ fuz: 1
644
+ }
645
+ }
646
+
647
+ export const foo = test("1")
648
+ `;
649
+
650
+ const { sf, tc } = setupTestEnv(sc);
651
+ const converter = new TsConverter(tc);
652
+ const XLR = converter.convertSourceFile(sf).data.types;
653
+
654
+ expect(XLR).toMatchSnapshot();
655
+ });
656
+
657
+ test("Arrow function with object return type", () => {
658
+ const sc = `
659
+ interface Bar {
660
+ foo: string;
661
+ fuz: number;
662
+ }
663
+
664
+ export const foo = (): Bar => {
665
+ return {
666
+ foo: "1",
667
+ fuz: 1,
668
+ };
669
+ };
670
+
671
+ `;
672
+
673
+ const { sf, tc } = setupTestEnv(sc);
674
+ const converter = new TsConverter(tc);
675
+ const XLR = converter.convertSourceFile(sf).data.types;
676
+
677
+ expect(XLR).toMatchSnapshot();
678
+ });
679
+
680
+ test("Aliased variable", () => {
681
+ const sc = `
682
+ interface Bar {
683
+ foo: string
684
+ fuz: number
685
+ }
686
+
687
+ function test(arg1: string): Bar {
688
+ return {
689
+ foo: "1",
690
+ fuz: 1
691
+ }
692
+ }
693
+
694
+ const foo = test("1")
695
+
696
+ export const bar = foo
697
+ `;
698
+
699
+ const { sf, tc } = setupTestEnv(sc);
700
+ const converter = new TsConverter(tc);
701
+ const XLR = converter.convertSourceFile(sf).data.types;
702
+
703
+ expect(XLR).toMatchSnapshot();
704
+ });
705
+
706
+ test("gets named tuple members", () => {
707
+ const sc = `
708
+ export type Foo = [argName: string, argValue: string];
709
+ `;
710
+
711
+ const { sf, tc } = setupTestEnv(sc);
712
+ const converter = new TsConverter(tc);
713
+ const XLR = converter.convertSourceFile(sf).data.types;
714
+
715
+ expect(XLR).toMatchSnapshot();
716
+ });
717
+
718
+ test("Arrow function with parameters", () => {
719
+ const sc = `
720
+ interface Bar {
721
+ foo: string
722
+ fuz: number
723
+ }
724
+
725
+ export const foo = (input: number): Bar => {
726
+ return {
727
+ foo: "1",
728
+ fuz: 1,
729
+ };
730
+ };
731
+ `;
732
+
733
+ const { sf, tc } = setupTestEnv(sc);
734
+ const converter = new TsConverter(tc);
735
+ const XLR = converter.convertSourceFile(sf).data.types;
736
+
737
+ expect(XLR).toMatchSnapshot();
738
+ });
739
+
740
+ test("named tuples in generics", () => {
741
+ const sc = `
742
+ type Foo<T> = T;
743
+ export type Bar = Foo<[argName: string, argValue: string]>;
744
+ `;
745
+
746
+ const { sf, tc } = setupTestEnv(sc);
747
+ const converter = new TsConverter(tc);
748
+ const XLR = converter.convertSourceFile(sf).data.types;
749
+
750
+ expect(XLR).toMatchSnapshot();
751
+ });
752
+
753
+ test("Aliased Arrow function exports its own name", () => {
754
+ const sc = `
755
+ interface Bar {
756
+ foo: string
757
+ fuz: number
758
+ }
759
+
760
+ export const foo = (input: number): Bar => {
761
+ return {
762
+ foo: "1",
763
+ fuz: 1,
764
+ };
765
+ };
766
+
767
+ export const baz = foo
768
+ `;
769
+
770
+ const { sf, tc } = setupTestEnv(sc);
771
+ const converter = new TsConverter(tc);
772
+ const XLR = converter.convertSourceFile(sf).data.types;
773
+
774
+ expect(XLR).toMatchSnapshot();
775
+ });
776
+ });