|
| 1 | +const fs = require('fs'); |
| 2 | +const path = require('path'); |
| 3 | +const _ = require('lodash'); |
| 4 | +const { expandUnitTests, checkForAPIKey} = require('./api'); |
| 5 | +// const {PYTHAGORA_UNIT_DIR} = require("../const/common"); |
| 6 | +// const generator = require("@babel/generator").default; |
| 7 | +const {delay, checkDirectoryExists} = require("../utils/common"); |
| 8 | +const { |
| 9 | + getAstFromFilePath, |
| 10 | + getRelatedTestImports, |
| 11 | + getSourceCodeFromAst, |
| 12 | + getModuleTypeFromFilePath |
| 13 | +} = require("../utils/code"); |
| 14 | +const { getFunctionsForExport } = require("./unitTests") |
| 15 | +const {getRelativePath, getFolderTreeItem, getTestFolderPath, checkPathType, isPathInside} = require("../utils/files"); |
| 16 | +const {initScreenForUnitTests} = require("./cmdGUI"); |
| 17 | +const { forEach } = require('lodash'); |
| 18 | +//const {green, red, blue, bold, reset} = require('../utils/cmdPrint').colors; |
| 19 | + |
| 20 | +let functionList = {}, |
| 21 | + leftPanel, |
| 22 | + rightPanel, |
| 23 | + screen, |
| 24 | + scrollableContent, |
| 25 | + spinner, |
| 26 | + rootPath = '', |
| 27 | + queriedPath = '', |
| 28 | + folderStructureTree = [], |
| 29 | + testsGenerated = [], |
| 30 | + errors = [], |
| 31 | + ignoreFolders = ['node_modules', 'pythagora_tests'], |
| 32 | + processExtensions = ['.js', '.ts'], |
| 33 | + ignoreErrors = ['BABEL_PARSER_SYNTAX_ERROR'], |
| 34 | + force |
| 35 | +; |
| 36 | + |
| 37 | +//the same like in uniTests.js - TODO: reuse it |
| 38 | +async function saveTests(filePath, fileName, testData) { |
| 39 | + let dir = filePath.substring(0, filePath.lastIndexOf('/')); |
| 40 | + //dir = getTestFolderPath(filePath, rootPath); |
| 41 | + |
| 42 | + if (!await checkDirectoryExists(dir)) { |
| 43 | + fs.mkdirSync(dir, { recursive: true }); |
| 44 | + } |
| 45 | + |
| 46 | + let testPath = path.join(dir, `/${fileName}`); |
| 47 | + fs.writeFileSync(testPath, testData); |
| 48 | + return testPath; |
| 49 | +} |
| 50 | + |
| 51 | +function reformatDataForPythagoraAPI(filePath, testCode, relatedCode, syntaxType) { |
| 52 | + const importedFiles = []; |
| 53 | + |
| 54 | + _.forEach(relatedCode, (f) => { |
| 55 | + const fileFolderPath = f.filePath.substring(0, f.filePath.lastIndexOf('/')) |
| 56 | + const pathRelativeToTest = getRelativePath(f.filePath, getTestFolderPath(fileFolderPath, rootPath)); |
| 57 | + f.pathRelativeToTest = pathRelativeToTest; |
| 58 | + //f.fileName = f.fileName.substring(f.fileName.lastIndexOf('/') + 1); |
| 59 | + |
| 60 | + if (!importedFiles.find(i => i.filePath == f.filePath)) { |
| 61 | + importedFiles.push({ |
| 62 | + fileName: f.fileName.substring(f.fileName.lastIndexOf('/') + 1), |
| 63 | + filePath: f.filePath, |
| 64 | + pathRelativeToTest: f.pathRelativeToTest, |
| 65 | + syntaxType: f.syntaxType |
| 66 | + }) |
| 67 | + } |
| 68 | + }) |
| 69 | + |
| 70 | + const testFilePath = getTestFolderPath(filePath, rootPath); |
| 71 | + const pathRelativeToTest = getRelativePath(filePath, testFilePath); |
| 72 | + |
| 73 | + return { |
| 74 | + testFileName: filePath.substring(filePath.lastIndexOf('/') + 1), |
| 75 | + testCode, |
| 76 | + relatedCode, |
| 77 | + importedFiles, |
| 78 | + isES6Syntax: syntaxType === 'ES6', |
| 79 | + pathRelativeToTest |
| 80 | + } |
| 81 | +} |
| 82 | + |
| 83 | +async function createAdditionalTests(filePath, prefix) { |
| 84 | + //TODO-1: get test source code and source code of related functions (import, require) |
| 85 | + const ast = await getAstFromFilePath(filePath); |
| 86 | + let syntaxType = await getModuleTypeFromFilePath(ast); |
| 87 | + |
| 88 | + //const testCode = getSourceCodeFromAst(ast); |
| 89 | + |
| 90 | + const importRegex = /^(.*import.*|.*require.*)$/gm; |
| 91 | + let testCode = getSourceCodeFromAst(ast); |
| 92 | + testCode = testCode.replace(importRegex, ''); |
| 93 | + |
| 94 | + |
| 95 | + const relatedTestCode = getRelatedTestImports(ast, filePath, functionList) |
| 96 | + |
| 97 | + // Now we have test source code and related test functions source code (imported or required) |
| 98 | + // TODO-1: reformat data |
| 99 | + |
| 100 | + const testPath = getTestFolderPath(filePath, rootPath) |
| 101 | + const formattedData = reformatDataForPythagoraAPI(filePath, testCode, relatedTestCode, syntaxType) |
| 102 | + |
| 103 | + // TODO-2: send date to API for processing |
| 104 | + // TODO-3: check only for *.test.js files pattern |
| 105 | + // TODO-4: save processing results data |
| 106 | + |
| 107 | + console.log('formattedData: ', formattedData) |
| 108 | + let { tests, error } = await expandUnitTests(formattedData); |
| 109 | + if (tests) { |
| 110 | + await saveTests(testPath, formattedData.testFileName, tests); |
| 111 | + } |
| 112 | + |
| 113 | + // TODO-5: display processing progress in a proper way |
| 114 | +} |
| 115 | + |
| 116 | +function checkForTestFilePath(filePath) { |
| 117 | + const pattern = /test\.(js|ts)$/; |
| 118 | + return pattern.test(filePath); |
| 119 | + // if (pattern.test(filePath)) return true |
| 120 | + // else |
| 121 | +} |
| 122 | + |
| 123 | +async function traverseDirectoryTests(directory, prefix = '') { |
| 124 | + if (await checkPathType(directory) === 'file' && checkForTestFilePath(directory)) { |
| 125 | + const newPrefix = `| ${prefix}| `; |
| 126 | + return await createAdditionalTests(directory, newPrefix); |
| 127 | + } else if (await checkPathType(directory) === 'file' && !checkForTestFilePath(directory)) { |
| 128 | + throw new Error('Invalid test file path'); |
| 129 | + } |
| 130 | + |
| 131 | + const files = fs.readdirSync(directory); |
| 132 | + for (const file of files) { |
| 133 | + const absolutePath = path.join(directory, file); |
| 134 | + const stat = fs.statSync(absolutePath); |
| 135 | + //const isLast = files.indexOf(file) === files.length - 1; |
| 136 | + if (stat.isDirectory()) { |
| 137 | + if (ignoreFolders.includes(path.basename(absolutePath)) || path.basename(absolutePath).charAt(0) === '.') continue; |
| 138 | + |
| 139 | + //const newPrefix = isLast ? `${prefix} ` : `${prefix}| `; |
| 140 | + await traverseDirectoryTests(absolutePath, prefix); |
| 141 | + } else { |
| 142 | + if (!processExtensions.includes(path.extname(absolutePath)) || !checkForTestFilePath(file)) continue; |
| 143 | + //const newPrefix = isLast ? `| ${prefix} ` : `| ${prefix}| `; |
| 144 | + //await createAdditionalTests(absolutePath, newPrefix); |
| 145 | + await createAdditionalTests(absolutePath, prefix); |
| 146 | + } |
| 147 | + } |
| 148 | +} |
| 149 | + |
| 150 | +async function expandTestsForDirectory(args) { |
| 151 | + let pathToProcess = args.expand_path, |
| 152 | + force = args.force; |
| 153 | + |
| 154 | + checkForAPIKey(); |
| 155 | + queriedPath = path.resolve(pathToProcess); |
| 156 | + rootPath = process.cwd(); |
| 157 | + ({ screen, spinner, scrollableContent } = initScreenForUnitTests()); |
| 158 | + functionList = await getFunctionsForExport(rootPath) |
| 159 | + |
| 160 | + await traverseDirectoryTests(queriedPath, false) |
| 161 | + |
| 162 | + process.exit(0); |
| 163 | +} |
| 164 | + |
| 165 | +module.exports = { |
| 166 | + expandTestsForDirectory |
| 167 | +} |
0 commit comments