11const fs = require ( 'fs' ) ;
22const path = require ( 'path' ) ;
33const _ = require ( 'lodash' ) ;
4- const { getUnitTests , checkForAPIKey } = require ( './api' ) ;
4+ const API = require ( './api' ) ;
55const { PYTHAGORA_UNIT_DIR } = require ( "../const/common" ) ;
66const generator = require ( "@babel/generator" ) . default ;
77const { checkDirectoryExists} = require ( "../utils/common" ) ;
@@ -34,13 +34,45 @@ let functionList = {},
3434 force
3535;
3636
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 ) {
3851 try {
3952 let exportsFn = [ ] ;
4053 let exportsObj = [ ] ;
4154 let functions = [ ] ;
4255 let ast = await getAstFromFilePath ( filePath ) ;
4356 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+
4476 processAst ( ast , ( funcName , path , type ) => {
4577 if ( type === 'exportFn' || type === 'exportFnDef' ) {
4678 exportsFn . push ( funcName ) ;
@@ -116,7 +148,7 @@ async function reformatDataForPythagoraAPI(funcData, filePath, testFilePath) {
116148 return funcData ;
117149}
118150
119- async function createTests ( filePath , prefix , funcToTest ) {
151+ async function createTests ( filePath , prefix , funcToTest , processingFunction = 'getUnitTests' ) {
120152 try {
121153 let extension = path . extname ( filePath ) ;
122154 let ast = await getAstFromFilePath ( filePath ) ;
@@ -173,7 +205,7 @@ async function createTests(filePath, prefix, funcToTest) {
173205 }
174206
175207 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 ) => {
177209 scrollableContent . setContent ( content ) ;
178210 scrollableContent . setScrollPerc ( 100 ) ;
179211 screen . render ( ) ;
@@ -217,42 +249,49 @@ async function saveTests(filePath, name, testData) {
217249 return testPath ;
218250}
219251
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' ) ;
223255 const newPrefix = `| ${ prefix } | ` ;
224- return await createTests ( directory , newPrefix , funcName ) ;
256+ return await createTests ( file , newPrefix , funcName , processingFunction ) ;
225257 }
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 ;
231258
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 )
233268
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 )
236279
237- if ( onlyCollectFunctionData && isPathInside ( path . dirname ( queriedPath ) , absolutePath ) ) {
280+ if ( onlyCollectFunctionData ) {
281+ if ( isPathInside ( path . dirname ( queriedPath ) , absolutePath ) ) {
238282 updateFolderTree ( prefix , isLast , absolutePath ) ;
239283 }
240-
241- const newPrefix = isLast ? `${ prefix } ` : `${ prefix } | ` ;
242- await traverseDirectory ( absolutePath , onlyCollectFunctionData , newPrefix , funcName ) ;
284+ await processFile ( absolutePath , filesToProcess ) ;
243285 } 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 ) ;
254288 }
255289 }
290+
291+ while ( filesToProcess . length > 0 ) {
292+ const nextFile = filesToProcess . shift ( ) ;
293+ await traverseDirectory ( nextFile , onlyCollectFunctionData , prefix , funcName , filesToProcess , processingFunction ) ;
294+ }
256295}
257296
258297function updateFolderTree ( prefix , isLast , absolutePath ) {
@@ -268,19 +307,20 @@ async function getFunctionsForExport(dirPath) {
268307 return functionList ;
269308}
270309
271- async function generateTestsForDirectory ( args ) {
310+ async function generateTestsForDirectory ( args , processingFunction = 'getUnitTests' ) {
272311 let pathToProcess = args . path ,
273312 funcName = args . func ;
274313 force = args . force ;
275314
276- checkForAPIKey ( ) ;
315+ API . checkForAPIKey ( ) ;
277316 queriedPath = path . resolve ( pathToProcess ) ;
278317 rootPath = process . cwd ( ) ;
279318 ( { screen, spinner, scrollableContent } = initScreenForUnitTests ( ) ) ;
280319
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 ) ;
284324
285325 screen . destroy ( ) ;
286326 process . stdout . write ( '\x1B[2J\x1B[0f' ) ;
0 commit comments