1
1
const fs = require ( 'fs' ) ;
2
2
const path = require ( 'path' ) ;
3
3
const _ = require ( 'lodash' ) ;
4
- const { getUnitTests , checkForAPIKey } = require ( './api' ) ;
4
+ const API = require ( './api' ) ;
5
5
const { PYTHAGORA_UNIT_DIR } = require ( "../const/common" ) ;
6
6
const generator = require ( "@babel/generator" ) . default ;
7
7
const { checkDirectoryExists} = require ( "../utils/common" ) ;
@@ -34,13 +34,45 @@ let functionList = {},
34
34
force
35
35
;
36
36
37
- async function processFile ( filePath ) {
37
+ function resolveFilePath ( filePath , extension ) {
38
+ if ( fs . existsSync ( filePath ) ) {
39
+ return filePath ;
40
+ }
41
+
42
+ const filePathWithExtension = `${ filePath } ${ extension } ` ;
43
+ if ( fs . existsSync ( filePathWithExtension ) ) {
44
+ return filePathWithExtension ;
45
+ }
46
+
47
+ return undefined ;
48
+ }
49
+
50
+ async function processFile ( filePath , filesToProcess ) {
38
51
try {
39
52
let exportsFn = [ ] ;
40
53
let exportsObj = [ ] ;
41
54
let functions = [ ] ;
42
55
let ast = await getAstFromFilePath ( filePath ) ;
43
56
let syntaxType = await getModuleTypeFromFilePath ( ast ) ;
57
+ let extension = path . extname ( filePath ) ;
58
+
59
+ // Analyze dependencies
60
+ ast . program . body . forEach ( node => {
61
+ if ( node . type === "ImportDeclaration" ) {
62
+ let importedFile = path . resolve ( path . dirname ( filePath ) , node . source . value ) ;
63
+ importedFile = resolveFilePath ( importedFile , extension ) ;
64
+ if ( importedFile && ! filesToProcess . includes ( importedFile ) ) {
65
+ filesToProcess . push ( importedFile ) ;
66
+ }
67
+ } else if ( node . type === "VariableDeclaration" && node . declarations [ 0 ] . init . type === "CallExpression" && node . declarations [ 0 ] . init . callee . name === "require" ) {
68
+ let importedFile = path . resolve ( path . dirname ( filePath ) , node . declarations [ 0 ] . init . arguments [ 0 ] . value ) ;
69
+ importedFile = resolveFilePath ( importedFile , extension ) ;
70
+ if ( importedFile && ! filesToProcess . includes ( importedFile ) ) {
71
+ filesToProcess . push ( importedFile ) ;
72
+ }
73
+ }
74
+ } ) ;
75
+
44
76
processAst ( ast , ( funcName , path , type ) => {
45
77
if ( type === 'exportFn' || type === 'exportFnDef' ) {
46
78
exportsFn . push ( funcName ) ;
@@ -116,7 +148,7 @@ async function reformatDataForPythagoraAPI(funcData, filePath, testFilePath) {
116
148
return funcData ;
117
149
}
118
150
119
- async function createTests ( filePath , prefix , funcToTest ) {
151
+ async function createTests ( filePath , prefix , funcToTest , processingFunction = 'getUnitTests' ) {
120
152
try {
121
153
let extension = path . extname ( filePath ) ;
122
154
let ast = await getAstFromFilePath ( filePath ) ;
@@ -173,7 +205,7 @@ async function createTests(filePath, prefix, funcToTest) {
173
205
}
174
206
175
207
let formattedData = await reformatDataForPythagoraAPI ( funcData , filePath , getTestFolderPath ( filePath , rootPath ) ) ;
176
- let { tests, error } = await getUnitTests ( formattedData , ( content ) => {
208
+ let { tests, error } = await API [ processingFunction ] ( formattedData , ( content ) => {
177
209
scrollableContent . setContent ( content ) ;
178
210
scrollableContent . setScrollPerc ( 100 ) ;
179
211
screen . render ( ) ;
@@ -217,42 +249,49 @@ async function saveTests(filePath, name, testData) {
217
249
return testPath ;
218
250
}
219
251
220
- async function traverseDirectory ( directory , onlyCollectFunctionData , prefix = '' , funcName ) {
221
- if ( await checkPathType ( directory ) === 'file' && ! onlyCollectFunctionData ) {
222
- if ( ! processExtensions . includes ( path . extname ( directory ) ) ) throw new Error ( 'File extension is not supported' ) ;
252
+ async function traverseDirectory ( file , onlyCollectFunctionData , prefix = '' , funcName , filesToProcess = [ file ] , processingFunction ) {
253
+ if ( await checkPathType ( file ) === 'file' && ! onlyCollectFunctionData ) {
254
+ if ( ! processExtensions . includes ( path . extname ( file ) ) ) throw new Error ( 'File extension is not supported' ) ;
223
255
const newPrefix = `| ${ prefix } | ` ;
224
- return await createTests ( directory , newPrefix , funcName ) ;
256
+ return await createTests ( file , newPrefix , funcName , processingFunction ) ;
225
257
}
226
- const files = fs . readdirSync ( directory ) ;
227
- for ( const file of files ) {
228
- const absolutePath = path . join ( directory , file ) ;
229
- const stat = fs . statSync ( absolutePath ) ;
230
- const isLast = files . indexOf ( file ) === files . length - 1 ;
231
258
232
- if ( ignoreFilesEndingWith . some ( ending => file . endsWith ( ending ) ) ) continue ;
259
+ const absolutePath = path . resolve ( file ) ;
260
+ const stat = fs . statSync ( absolutePath ) ;
261
+ const isLast = filesToProcess . length === 0 ;
262
+
263
+ if ( ignoreFilesEndingWith . some ( ending => file . endsWith ( ending ) ) ) return ;
264
+
265
+ if ( stat . isDirectory ( ) ) {
266
+ if ( ignoreFolders . includes ( path . basename ( absolutePath ) ) || path . basename ( absolutePath ) . charAt ( 0 ) === '.' ) return ;
267
+ console . log ( file )
233
268
234
- if ( stat . isDirectory ( ) ) {
235
- if ( ignoreFolders . includes ( path . basename ( absolutePath ) ) || path . basename ( absolutePath ) . charAt ( 0 ) === '.' ) continue ;
269
+ if ( onlyCollectFunctionData && isPathInside ( path . dirname ( queriedPath ) , absolutePath ) ) {
270
+ updateFolderTree ( prefix , isLast , absolutePath ) ;
271
+ }
272
+
273
+ const newPrefix = isLast ? `${ prefix } ` : `${ prefix } | ` ;
274
+ const directoryFiles = fs . readdirSync ( absolutePath ) ;
275
+ filesToProcess . push ( ...directoryFiles . map ( f => path . join ( absolutePath , f ) ) ) ;
276
+ } else {
277
+ if ( ! processExtensions . includes ( path . extname ( absolutePath ) ) ) return ;
278
+ console . log ( file )
236
279
237
- if ( onlyCollectFunctionData && isPathInside ( path . dirname ( queriedPath ) , absolutePath ) ) {
280
+ if ( onlyCollectFunctionData ) {
281
+ if ( isPathInside ( path . dirname ( queriedPath ) , absolutePath ) ) {
238
282
updateFolderTree ( prefix , isLast , absolutePath ) ;
239
283
}
240
-
241
- const newPrefix = isLast ? `${ prefix } ` : `${ prefix } | ` ;
242
- await traverseDirectory ( absolutePath , onlyCollectFunctionData , newPrefix , funcName ) ;
284
+ await processFile ( absolutePath , filesToProcess ) ;
243
285
} else {
244
- if ( ! processExtensions . includes ( path . extname ( absolutePath ) ) ) continue ;
245
- if ( onlyCollectFunctionData ) {
246
- if ( isPathInside ( path . dirname ( queriedPath ) , absolutePath ) ) {
247
- updateFolderTree ( prefix , isLast , absolutePath ) ;
248
- }
249
- await processFile ( absolutePath ) ;
250
- } else {
251
- const newPrefix = isLast ? `| ${ prefix } ` : `| ${ prefix } | ` ;
252
- await createTests ( absolutePath , newPrefix , funcName ) ;
253
- }
286
+ const newPrefix = isLast ? `| ${ prefix } ` : `| ${ prefix } | ` ;
287
+ await createTests ( absolutePath , newPrefix , funcName , processingFunction ) ;
254
288
}
255
289
}
290
+
291
+ while ( filesToProcess . length > 0 ) {
292
+ const nextFile = filesToProcess . shift ( ) ;
293
+ await traverseDirectory ( nextFile , onlyCollectFunctionData , prefix , funcName , filesToProcess , processingFunction ) ;
294
+ }
256
295
}
257
296
258
297
function updateFolderTree ( prefix , isLast , absolutePath ) {
@@ -268,19 +307,20 @@ async function getFunctionsForExport(dirPath) {
268
307
return functionList ;
269
308
}
270
309
271
- async function generateTestsForDirectory ( args ) {
310
+ async function generateTestsForDirectory ( args , processingFunction = 'getUnitTests' ) {
272
311
let pathToProcess = args . path ,
273
312
funcName = args . func ;
274
313
force = args . force ;
275
314
276
- checkForAPIKey ( ) ;
315
+ API . checkForAPIKey ( ) ;
277
316
queriedPath = path . resolve ( pathToProcess ) ;
278
317
rootPath = process . cwd ( ) ;
279
318
( { screen, spinner, scrollableContent } = initScreenForUnitTests ( ) ) ;
280
319
281
- await traverseDirectory ( rootPath , true ) ; // first pass: collect all function names and codes
282
- await traverseDirectory ( rootPath , true ) ; // second pass: collect all related functions
283
- await traverseDirectory ( queriedPath , false , undefined , funcName ) ; // second pass: print functions and their related functions
320
+ let filesToProcess = [ ] ;
321
+ await traverseDirectory ( queriedPath , true , undefined , funcName , filesToProcess , processingFunction ) ;
322
+ await traverseDirectory ( queriedPath , true , undefined , funcName , filesToProcess , processingFunction ) ;
323
+ await traverseDirectory ( queriedPath , false , undefined , funcName , filesToProcess , processingFunction ) ;
284
324
285
325
screen . destroy ( ) ;
286
326
process . stdout . write ( '\x1B[2J\x1B[0f' ) ;
0 commit comments