1
+
2
+ import { Baseline } from "../_namespaces/Harness" ;
3
+ import * as ts from "../_namespaces/ts" ;
4
+ describe ( "unittests:: canWatch::" , ( ) => {
5
+ baselineCanWatch (
6
+ "canWatchDirectoryOrFile" ,
7
+ ( ) => `Determines if given directory or file can be watched` ,
8
+ ( paths , longestPathLength , baseline ) => {
9
+ const testType = "canWatchDirectoryOrFile" ;
10
+ const maxLengths = [ longestPathLength + "/package.json" . length , testType . length ] as const ;
11
+ pushHeader ( baseline , [ "Directory" , testType ] , maxLengths ) ;
12
+ paths . forEach ( path => baselineCanWatchDirectoryOrFile ( path , maxLengths ) ) ;
13
+ pushHeader ( baseline , [ "File" , testType ] , maxLengths ) ;
14
+ paths . forEach ( path => baselineCanWatchDirectoryOrFile ( combinePaths ( path , "package.json" ) , maxLengths ) ) ;
15
+ baseline . push ( "" , "" ) ;
16
+ function baselineCanWatchDirectoryOrFile ( path : ts . Path , maxLengths : readonly number [ ] ) {
17
+ pushRow ( baseline , [ path , `${ ts . canWatchDirectoryOrFile ( path ) } ` ] , maxLengths ) ;
18
+ }
19
+ } ,
20
+ ) ;
21
+
22
+ baselineCanWatch (
23
+ "canWatchAtTypes" ,
24
+ ( ) => `Determines if given node_modules/@types can be watched.\r\nThese are the typeRoots calculated because user didnt specify typeRoots in compierOptions` ,
25
+ ( paths , longestPathLength , baseline ) => {
26
+ const testType = "canWatchAtTypes" ;
27
+ const maxLengths = [ longestPathLength + "/node_modules/@types" . length , testType . length ] as const ;
28
+ baselineCanWatchForRoot ( paths , baseline , root => {
29
+ pushHeader ( baseline , [ "Directory" , testType ] , maxLengths ) ;
30
+ paths . forEach ( path => {
31
+ path = combinePaths ( path , "node_modules/@types" ) ;
32
+ pushRow ( baseline , [ path , `${ ts . canWatchAtTypes ( path , root ) } ` ] , maxLengths ) ;
33
+ } ) ;
34
+ } ) ;
35
+ } ,
36
+ ) ;
37
+
38
+ baselineCanWatch (
39
+ "canWatchAffectingLocation" ,
40
+ ( ) => `Determines if package.json that was found during module resolution and change in it will affect resolution can be watched.` ,
41
+ ( paths , longestPathLength , baseline ) => {
42
+ const testType = "canWatchAffectingLocation" ;
43
+ const maxLengths = [ longestPathLength + "/package.json" . length , testType . length ] as const ;
44
+ pushHeader ( baseline , [ "File" , testType ] , maxLengths ) ;
45
+ paths . forEach ( path => {
46
+ path = combinePaths ( path , "package.json" ) ;
47
+ pushRow ( baseline , [ path , `${ ts . canWatchAffectingLocation ( path ) } ` ] , maxLengths ) ;
48
+ } ) ;
49
+ baseline . push ( "" , "" ) ;
50
+ } ,
51
+ ) ;
52
+
53
+ baselineGetDirectoryToWatchOfFailedLookup ( "getDirectoryToWatchFailedLookupLocationNodeModules" , "node_modules" ) ;
54
+ baselineGetDirectoryToWatchOfFailedLookup ( "getDirectoryToWatchFailedLookupLocationAtTypes" , "node_modules/@types" ) ;
55
+ baselineGetDirectoryToWatchOfFailedLookup ( "getDirectoryToWatchFailedLookupLocation" , "" ) ;
56
+ function baselineGetDirectoryToWatchOfFailedLookup (
57
+ scenario : string ,
58
+ forPath : "node_modules" | "node_modules/@types" | "" ,
59
+ ) {
60
+ baselineCanWatch (
61
+ scenario ,
62
+ ( ) => `Determines whether to watch given failed lookup location (file that didnt exist) when resolving module.\r\nIt also determines the directory to watch and whether to watch it recursively or not.` ,
63
+ ( paths , longestPathLength , baseline ) => {
64
+ const recursive = "Recursive" ;
65
+ const maxLength = longestPathLength + ts . combinePaths ( forPath , "dir/subdir/somefile.d.ts" ) . length ;
66
+ const maxLengths = [ maxLength , maxLength , recursive . length ] as const ;
67
+ baselineCanWatchForRoot ( paths , baseline , root => {
68
+ pushHeader ( baseline , [ "Location" , "getDirectoryToWatchFailedLookupLocation" , recursive ] , maxLengths ) ;
69
+ paths . forEach ( path => {
70
+ baselineGetDirectoryToWatchFailedLookupLocation ( combinePaths ( path , forPath , "somefile.d.ts" ) , root , maxLengths ) ;
71
+ baselineGetDirectoryToWatchFailedLookupLocation ( combinePaths ( path , forPath , "dir/somefile.d.ts" ) , root , maxLengths ) ;
72
+ baselineGetDirectoryToWatchFailedLookupLocation ( combinePaths ( path , forPath , "dir/subdir/somefile.d.ts" ) , root , maxLengths ) ;
73
+ } ) ;
74
+ } ) ;
75
+ function baselineGetDirectoryToWatchFailedLookupLocation ( path : ts . Path , root : ts . Path | undefined , maxLengths : readonly number [ ] ) {
76
+ const result = ts . getDirectoryToWatchFailedLookupLocation (
77
+ path ,
78
+ path ,
79
+ root ,
80
+ root ,
81
+ root !== undefined ? root . split ( ts . directorySeparator ) . length : 0 ,
82
+ ts . returnUndefined ,
83
+ ) ;
84
+ pushRow ( baseline , [ path , result ? result . dir : "" , result ? `${ ! result . nonRecursive } ` : "" ] , maxLengths ) ;
85
+ }
86
+ } ,
87
+ ) ;
88
+ }
89
+
90
+ baselineCanWatch (
91
+ "getDirectoryToWatchFailedLookupLocationFromTypeRoot" ,
92
+ ( ) => `When watched typeRoot handler is invoked, this method determines the directory for which the failedLookupLocation would need to be invalidated.\r\nSince this is invoked only when watching default typeRoot and is used to handle flaky directory watchers, this is used as a fail safe where if failed lookup starts with returned directory we will invalidate that resolution.` ,
93
+ ( paths , longestPathLength , baseline ) => {
94
+ const maxLength = longestPathLength + "/node_modules/@types" . length ;
95
+ const maxLengths = [ maxLength , maxLength ] as const ;
96
+ baselineCanWatchForRoot ( paths , baseline , root => {
97
+ pushHeader ( baseline , [ "Directory" , "getDirectoryToWatchFailedLookupLocationFromTypeRoot" ] , maxLengths ) ;
98
+ paths . forEach ( path => {
99
+ path = combinePaths ( path , "node_modules/@types" ) ;
100
+ // This is invoked only on paths that are watched
101
+ if ( ! ts . canWatchAtTypes ( path , root ) ) return ;
102
+ const result = ts . getDirectoryToWatchFailedLookupLocationFromTypeRoot (
103
+ path ,
104
+ path ,
105
+ root ,
106
+ ts . returnTrue ,
107
+ ) ;
108
+ pushRow ( baseline , [ path , result !== undefined ? result : "" ] , maxLengths ) ;
109
+ } ) ;
110
+ } ) ;
111
+ } ,
112
+ ) ;
113
+
114
+ function baselineCanWatchForRoot ( paths : readonly ts . Path [ ] , baseline : string [ ] , baselineForRoot : ( root : ts . Path | undefined ) => void ) {
115
+ paths . forEach ( baselineRoot ) ;
116
+ baselineRoot ( /*rootDirForResolution*/ undefined ) ;
117
+ baseline . push ( "" , "" ) ;
118
+
119
+ function baselineRoot ( rootDirForResolution : ts . Path | undefined ) {
120
+ const root = ts . getRootDirectoryOfResolutionCache ( rootDirForResolution , ts . returnUndefined ) as ts . Path ;
121
+ baseline . push ( "" , `## RootDirForResolution: ${ rootDirForResolution } ` , "" , `Root: ${ root } ` ) ;
122
+ baselineForRoot ( root ) ;
123
+ }
124
+ }
125
+
126
+ function baselineCanWatch (
127
+ scenario : string ,
128
+ info : ( ) => string ,
129
+ baselineOsRoot : ( paths : readonly ts . Path [ ] , longestPathLength : number , baseline : string [ ] ) => void ,
130
+ ) {
131
+ it ( `${ scenario } Posix` , ( ) => {
132
+ baselineCanWatchForOsRoot ( scenario , "Posix" , "/" , info , baselineOsRoot ) ;
133
+ } ) ;
134
+ it ( `${ scenario } Dos` , ( ) => {
135
+ baselineCanWatchForOsRoot ( scenario , "Dos" , "c:/" , info , baselineOsRoot ) ;
136
+ } ) ;
137
+ it ( `${ scenario } Unc` , ( ) => {
138
+ baselineCanWatchForOsRoot ( scenario , "Unc" , "//vda1cs4850/" , info , baselineOsRoot ) ;
139
+ } ) ;
140
+ it ( `${ scenario } UncDos` , ( ) => {
141
+ baselineCanWatchForOsRoot ( scenario , "UncDos" , "//vda1cs4850/c$" , info , baselineOsRoot ) ;
142
+ } ) ;
143
+ }
144
+
145
+ function baselineCanWatchForOsRoot (
146
+ scenario : string ,
147
+ suffix : string ,
148
+ osRoot : string ,
149
+ info : ( ) => string ,
150
+ baselineOsRoot : ( paths : readonly ts . Path [ ] , longestPathLength : number , baseline : string [ ] ) => void ,
151
+ ) {
152
+ const baseline : string [ ] = [ `# ${ scenario } ` , "" , info ( ) , "" ] ;
153
+ baseline . push ( `## Testing for ${ suffix } root: ${ osRoot } ` ) ;
154
+ const paths : ts . Path [ ] = [ ] ;
155
+ let longestPathLength = 0 ;
156
+ getPathsOfDifferentFoldersAt ( osRoot as ts . Path ) ;
157
+ osRoot = ts . ensureTrailingDirectorySeparator ( osRoot ) ;
158
+ const users = combinePaths ( osRoot , "users" ) ;
159
+ paths . push ( users ) ;
160
+ getPathsOfDifferentFoldersAt ( combinePaths ( users , "username" ) ) ;
161
+ const user = combinePaths ( osRoot , "user" ) ;
162
+ paths . push ( user ) ;
163
+ getPathsOfDifferentFoldersAt ( combinePaths ( user , "username" ) ) ;
164
+ baselineOsRoot ( paths , longestPathLength , baseline ) ;
165
+ Baseline . runBaseline ( `canWatch/${ scenario } ${ suffix } .baseline.md` , baseline . join ( "\r\n" ) ) ;
166
+ function getPathsOfDifferentFoldersAt ( root : ts . Path ) {
167
+ paths . push ( root ) ;
168
+ root = combinePaths ( root , "folderAtRoot" ) ;
169
+ paths . push ( root ) ;
170
+ for ( let i = 0 ; i < 5 ; i ++ ) {
171
+ root = combinePaths ( root , `folder${ i + 1 } ` ) ;
172
+ paths . push ( root ) ;
173
+ }
174
+ longestPathLength = Math . max ( ts . last ( paths ) . length , longestPathLength ) ;
175
+ }
176
+ }
177
+
178
+ function combinePaths ( path : string , addition : string , anotherAddition ?: string ) : ts . Path {
179
+ return ts . combinePaths ( path , addition , anotherAddition ) as ts . Path ;
180
+ }
181
+
182
+ function pushHeader ( baseline : string [ ] , headers : string [ ] , maxLengths : readonly number [ ] ) {
183
+ baseline . push ( "" ) ;
184
+ pushRow ( baseline , headers , maxLengths , /*addDivider*/ true ) ;
185
+ }
186
+
187
+ function pushRow ( baseline : string [ ] , columns : string [ ] , maxLengths : readonly number [ ] , addDivider ?: boolean ) {
188
+ let result = "|" ;
189
+ let divider = addDivider ? "|" : undefined ;
190
+ columns . forEach ( ( header , index ) => {
191
+ result += " " + ts . padRight ( header , maxLengths [ index ] ) + " |" ;
192
+ if ( addDivider ) divider += " " + "-" . repeat ( maxLengths [ index ] ) + " |" ;
193
+ } ) ;
194
+ baseline . push ( result ) ;
195
+ if ( divider ) baseline . push ( divider ) ;
196
+ }
197
+ } ) ;
0 commit comments