11/**
22 * @fileoverview Unit tests for TypeScript availability checks.
33 *
4- * Tests TypeScript-related constants:
5- * - Compiler availability detection
6- * - Target/module constants (ES2022, ESNext, CommonJS)
7- * - tsconfig.json paths and defaults
8- * - Type declaration patterns
9- * Frozen constants for TypeScript tooling.
4+ * Tests the pair of feature-detection getters:
5+ * - getTsTypesAvailable() — checks for typescript/lib/lib.d.ts
6+ * - getTsLibsAvailable() — checks for typescript/lib
7+ *
8+ * Each returns a cached boolean based on runtime module resolution.
109 */
1110
1211import { describe , expect , it } from 'vitest'
@@ -18,223 +17,39 @@ import {
1817
1918describe ( 'constants/typescript' , ( ) => {
2019 describe ( 'getTsTypesAvailable' , ( ) => {
21- it ( 'should return a boolean' , ( ) => {
22- const result = getTsTypesAvailable ( )
23- expect ( typeof result ) . toBe ( 'boolean' )
24- } )
25-
26- it ( 'should check for typescript/lib/lib.d.ts' , ( ) => {
27- const result = getTsTypesAvailable ( )
28- // Result depends on whether typescript is installed
29- expect ( [ true , false ] ) . toContain ( result )
20+ it ( 'returns a boolean' , ( ) => {
21+ expect ( typeof getTsTypesAvailable ( ) ) . toBe ( 'boolean' )
3022 } )
3123
32- it ( 'should be consistent across multiple calls' , ( ) => {
24+ it ( 'is cached — consistent across repeated calls' , ( ) => {
3325 const first = getTsTypesAvailable ( )
34- const second = getTsTypesAvailable ( )
35- expect ( first ) . toBe ( second )
36- } )
37-
38- it ( 'should not throw when typescript is not available' , ( ) => {
39- expect ( ( ) => getTsTypesAvailable ( ) ) . not . toThrow ( )
40- } )
41-
42- it ( 'should handle require.resolve internally' , ( ) => {
43- // This test verifies the function executes without errors
44- const result = getTsTypesAvailable ( )
45- expect ( result ) . toBeDefined ( )
26+ for ( let i = 0 ; i < 10 ; i ++ ) {
27+ expect ( getTsTypesAvailable ( ) ) . toBe ( first )
28+ }
4629 } )
4730 } )
4831
4932 describe ( 'getTsLibsAvailable' , ( ) => {
50- it ( 'should return a boolean' , ( ) => {
51- const result = getTsLibsAvailable ( )
52- expect ( typeof result ) . toBe ( 'boolean' )
33+ it ( 'returns a boolean' , ( ) => {
34+ expect ( typeof getTsLibsAvailable ( ) ) . toBe ( 'boolean' )
5335 } )
5436
55- it ( 'should check for typescript/lib' , ( ) => {
56- const result = getTsLibsAvailable ( )
57- // Result depends on whether typescript is installed
58- expect ( [ true , false ] ) . toContain ( result )
59- } )
60-
61- it ( 'should be consistent across multiple calls' , ( ) => {
37+ it ( 'is cached — consistent across repeated calls' , ( ) => {
6238 const first = getTsLibsAvailable ( )
63- const second = getTsLibsAvailable ( )
64- expect ( first ) . toBe ( second )
65- } )
66-
67- it ( 'should not throw when typescript is not available' , ( ) => {
68- expect ( ( ) => getTsLibsAvailable ( ) ) . not . toThrow ( )
69- } )
70-
71- it ( 'should handle require.resolve internally' , ( ) => {
72- // This test verifies the function executes without errors
73- const result = getTsLibsAvailable ( )
74- expect ( result ) . toBeDefined ( )
75- } )
76- } )
77-
78- describe ( 'TypeScript availability correlation' , ( ) => {
79- it ( 'should have same availability for both checks when typescript is present' , ( ) => {
80- const typesAvailable = getTsTypesAvailable ( )
81- const libsAvailable = getTsLibsAvailable ( )
82-
83- // If one is available, the other should be too (when typescript is installed)
84- if ( typesAvailable || libsAvailable ) {
85- // At least one should be true if typescript is available
86- expect ( typesAvailable || libsAvailable ) . toBe ( true )
87- }
88- } )
89-
90- it ( 'should both return false when typescript is not installed' , ( ) => {
91- const typesAvailable = getTsTypesAvailable ( )
92- const libsAvailable = getTsLibsAvailable ( )
93-
94- // If both are false, typescript is not installed
95- if ( ! typesAvailable && ! libsAvailable ) {
96- expect ( typesAvailable ) . toBe ( false )
97- expect ( libsAvailable ) . toBe ( false )
98- }
99- } )
100- } )
101-
102- describe ( 'error handling' , ( ) => {
103- it ( 'should gracefully handle module resolution errors for types' , ( ) => {
104- expect ( ( ) => {
105- const result = getTsTypesAvailable ( )
106- expect ( typeof result ) . toBe ( 'boolean' )
107- } ) . not . toThrow ( )
108- } )
109-
110- it ( 'should gracefully handle module resolution errors for libs' , ( ) => {
111- expect ( ( ) => {
112- const result = getTsLibsAvailable ( )
113- expect ( typeof result ) . toBe ( 'boolean' )
114- } ) . not . toThrow ( )
115- } )
116-
117- it ( 'should return false instead of throwing on module not found' , ( ) => {
118- // These functions should catch errors and return false
119- const types = getTsTypesAvailable ( )
120- const libs = getTsLibsAvailable ( )
121-
122- expect ( [ true , false ] ) . toContain ( types )
123- expect ( [ true , false ] ) . toContain ( libs )
124- } )
125- } )
126-
127- describe ( 'function independence' , ( ) => {
128- it ( 'should allow calling getTsTypesAvailable independently' , ( ) => {
129- const result = getTsTypesAvailable ( )
130- expect ( result ) . toBeDefined ( )
131- } )
132-
133- it ( 'should allow calling getTsLibsAvailable independently' , ( ) => {
134- const result = getTsLibsAvailable ( )
135- expect ( result ) . toBeDefined ( )
136- } )
137-
138- it ( 'should not affect each other when called in sequence' , ( ) => {
139- const types1 = getTsTypesAvailable ( )
140- const libs1 = getTsLibsAvailable ( )
141- const types2 = getTsTypesAvailable ( )
142- const libs2 = getTsLibsAvailable ( )
143-
144- expect ( types1 ) . toBe ( types2 )
145- expect ( libs1 ) . toBe ( libs2 )
146- } )
147-
148- it ( 'should not affect each other when called in reverse sequence' , ( ) => {
149- const libs1 = getTsLibsAvailable ( )
150- const types1 = getTsTypesAvailable ( )
151- const libs2 = getTsLibsAvailable ( )
152- const types2 = getTsTypesAvailable ( )
153-
154- expect ( types1 ) . toBe ( types2 )
155- expect ( libs1 ) . toBe ( libs2 )
156- } )
157- } )
158-
159- describe ( 'performance' , ( ) => {
160- it ( 'should execute quickly' , ( ) => {
161- const start = Date . now ( )
162- getTsTypesAvailable ( )
163- const duration = Date . now ( ) - start
164- // Should complete in under 100ms
165- expect ( duration ) . toBeLessThan ( 100 )
166- } )
167-
168- it ( 'should execute libs check quickly' , ( ) => {
169- const start = Date . now ( )
170- getTsLibsAvailable ( )
171- const duration = Date . now ( ) - start
172- // Should complete in under 100ms
173- expect ( duration ) . toBeLessThan ( 100 )
174- } )
175-
176- it ( 'should handle multiple rapid calls' , ( ) => {
177- const start = Date . now ( )
17839 for ( let i = 0 ; i < 10 ; i ++ ) {
179- getTsTypesAvailable ( )
180- getTsLibsAvailable ( )
40+ expect ( getTsLibsAvailable ( ) ) . toBe ( first )
18141 }
182- const duration = Date . now ( ) - start
183- // 20 calls should complete in under 500ms
184- expect ( duration ) . toBeLessThan ( 500 )
18542 } )
18643 } )
18744
188- describe ( 'return value validation' , ( ) => {
189- it ( 'should never return null for getTsTypesAvailable' , ( ) => {
190- const result = getTsTypesAvailable ( )
191- expect ( result ) . not . toBeNull ( )
192- } )
193-
194- it ( 'should never return undefined for getTsTypesAvailable' , ( ) => {
195- const result = getTsTypesAvailable ( )
196- expect ( result ) . not . toBeUndefined ( )
197- } )
198-
199- it ( 'should never return null for getTsLibsAvailable' , ( ) => {
200- const result = getTsLibsAvailable ( )
201- expect ( result ) . not . toBeNull ( )
202- } )
203-
204- it ( 'should never return undefined for getTsLibsAvailable' , ( ) => {
205- const result = getTsLibsAvailable ( )
206- expect ( result ) . not . toBeUndefined ( )
207- } )
208- } )
209-
210- describe ( 'real-world usage scenarios' , ( ) => {
211- it ( 'should be suitable for conditional TypeScript feature enablement' , ( ) => {
212- const typesAvailable = getTsTypesAvailable ( )
213-
214- if ( typesAvailable ) {
215- // TypeScript types are available, can use type checking
216- expect ( typesAvailable ) . toBe ( true )
217- } else {
218- // TypeScript types not available, skip type checking
219- expect ( typesAvailable ) . toBe ( false )
220- }
221- } )
222-
223- it ( 'should be suitable for library path resolution' , ( ) => {
224- const libsAvailable = getTsLibsAvailable ( )
225-
226- if ( libsAvailable ) {
227- // TypeScript libs are available, can load compiler
228- expect ( libsAvailable ) . toBe ( true )
229- } else {
230- // TypeScript libs not available, skip compilation
231- expect ( libsAvailable ) . toBe ( false )
232- }
233- } )
234-
235- it ( 'should support feature detection pattern' , ( ) => {
236- const hasTypeScript = getTsTypesAvailable ( ) && getTsLibsAvailable ( )
237- expect ( typeof hasTypeScript ) . toBe ( 'boolean' )
45+ describe ( 'independence' , ( ) => {
46+ it ( 'call order does not affect results (each getter memoizes independently)' , ( ) => {
47+ const typesFirst = getTsTypesAvailable ( )
48+ const libsAfterTypes = getTsLibsAvailable ( )
49+ const libsFirst = getTsLibsAvailable ( )
50+ const typesAfterLibs = getTsTypesAvailable ( )
51+ expect ( typesFirst ) . toBe ( typesAfterLibs )
52+ expect ( libsFirst ) . toBe ( libsAfterTypes )
23853 } )
23954 } )
24055} )
0 commit comments