@@ -23,16 +23,15 @@ import org.jetbrains.kotlin.idea.util.application.invokeLater
2323import org.jetbrains.kotlin.idea.util.application.runReadAction
2424import org.jetbrains.kotlin.idea.util.application.runWriteAction
2525import org.jetbrains.kotlin.konan.file.File
26+ import org.utbot.framework.plugin.api.TimeoutException
2627import org.utbot.intellij.plugin.ui.utils.showErrorDialogLater
2728import org.utbot.intellij.plugin.ui.utils.testModules
2829import settings.JsDynamicSettings
2930import settings.JsExportsSettings.endComment
3031import settings.JsExportsSettings.startComment
31- import settings.JsPackagesSettings.mochaData
32- import settings.JsPackagesSettings.nycData
33- import settings.JsPackagesSettings.ternData
3432import settings.JsTestGenerationSettings.dummyClassName
35- import settings.PackageData
33+ import settings.PackageDataService
34+ import settings.jsPackagesList
3635import utils.JsCmdExec
3736import utils.OsProvider
3837import java.io.IOException
@@ -58,9 +57,10 @@ object JsDialogProcessor {
5857 ) {
5958 override fun run (indicator : ProgressIndicator ) {
6059 invokeLater {
61- checkAndInstallRequirement(model.project, model.pathToNPM, mochaData)
62- checkAndInstallRequirement(model.project, model.pathToNPM, nycData)
63- checkAndInstallRequirement(model.project, model.pathToNPM, ternData)
60+ if (! PackageDataService (
61+ model.containingFilePath, model.project.basePath!! , model.pathToNPM
62+ ).checkAndInstallRequirements(project)
63+ ) return @invokeLater
6464 createDialog(model)?.let { dialogWindow ->
6565 if (! dialogWindow.showAndGet()) return @invokeLater
6666 // Since Tern.js accesses containing file, sync with file system required before test generation.
@@ -76,36 +76,31 @@ object JsDialogProcessor {
7676 }).queue()
7777 }
7878
79- private fun findNodeAndNPM (): Pair <String , String >? =
80- try {
81- val pathToNode = NodeJsLocalInterpreterManager .getInstance()
82- .interpreters.first().interpreterSystemIndependentPath
83- val (_, errorText) = JsCmdExec .runCommand(
84- shouldWait = true ,
85- cmd = arrayOf(" \" ${pathToNode} \" " , " -v" )
86- )
87- if (errorText.isNotEmpty()) throw NoSuchElementException ()
88- val pathToNPM =
89- pathToNode.substringBeforeLast(" /" ) + " /" + " npm" + OsProvider .getProviderByOs().npmPackagePostfix
90- pathToNode to pathToNPM
91- } catch (e: NoSuchElementException ) {
92- Messages .showErrorDialog(
93- " Node.js interpreter is not found in IDEA settings.\n " +
94- " Please set it in Settings > Languages & Frameworks > Node.js" ,
95- " Requirement Error"
96- )
97- logger.error { " Node.js interpreter was not found in IDEA settings." }
98- null
99- } catch (e: IOException ) {
100- Messages .showErrorDialog(
101- " Node.js interpreter path is corrupted in IDEA settings.\n " +
102- " Please check Settings > Languages & Frameworks > Node.js" ,
103- " Requirement Error"
104- )
105- logger.error { " Node.js interpreter path is corrupted in IDEA settings." }
106- null
107- }
108-
79+ private fun findNodeAndNPM (): Pair <String , String >? = try {
80+ val pathToNode =
81+ NodeJsLocalInterpreterManager .getInstance().interpreters.first().interpreterSystemIndependentPath
82+ val (_, errorText) = JsCmdExec .runCommand(
83+ shouldWait = true , cmd = arrayOf(" \" ${pathToNode} \" " , " -v" )
84+ )
85+ if (errorText.isNotEmpty()) throw NoSuchElementException ()
86+ val pathToNPM =
87+ pathToNode.substringBeforeLast(" /" ) + " /" + " npm" + OsProvider .getProviderByOs().npmPackagePostfix
88+ pathToNode to pathToNPM
89+ } catch (e: NoSuchElementException ) {
90+ Messages .showErrorDialog(
91+ " Node.js interpreter is not found in IDEA settings.\n " + " Please set it in Settings > Languages & Frameworks > Node.js" ,
92+ " Requirement Error"
93+ )
94+ logger.error { " Node.js interpreter was not found in IDEA settings." }
95+ null
96+ } catch (e: IOException ) {
97+ Messages .showErrorDialog(
98+ " Node.js interpreter path is corrupted in IDEA settings.\n " + " Please check Settings > Languages & Frameworks > Node.js" ,
99+ " Requirement Error"
100+ )
101+ logger.error { " Node.js interpreter path is corrupted in IDEA settings." }
102+ null
103+ }
109104
110105 private fun createJsTestModel (
111106 project : Project ,
@@ -138,7 +133,6 @@ object JsDialogProcessor {
138133 this .pathToNode = pathToNode
139134 this .pathToNPM = pathToNPM
140135 }
141-
142136 }
143137
144138 private fun createDialog (jsTestsModel : JsTestsModel ? ) = jsTestsModel?.let { JsDialogWindow (it) }
@@ -159,10 +153,8 @@ object JsDialogProcessor {
159153 val testDir = PsiDirectoryFactory .getInstance(project).createDirectory(
160154 model.testSourceRoot!!
161155 )
162- val testFileName = normalizedContainingFilePath.substringAfterLast(" /" )
163- .replace(Regex (" .js" ), " Test.js" )
164- val testGenerator = JsTestGenerator (
165- fileText = editor.document.text,
156+ val testFileName = normalizedContainingFilePath.substringAfterLast(" /" ).replace(Regex (" .js" ), " Test.js" )
157+ val testGenerator = JsTestGenerator (fileText = editor.document.text,
166158 sourceFilePath = normalizedContainingFilePath,
167159 projectPath = model.project.basePath?.replace(File .separator, " /" )
168160 ? : throw IllegalStateException (" Can't access project path." ),
@@ -267,45 +259,47 @@ object JsDialogProcessor {
267259 }
268260}
269261
270- fun checkAndInstallRequirement (
271- project : Project ,
272- pathToNPM : String ,
273- requirement : PackageData ,
274- ) {
275- if (! requirement.findPackageByNpm(project.basePath!! , pathToNPM)) {
276- installMissingRequirement(project, pathToNPM, requirement)
277- }
278- }
279-
280- private fun installMissingRequirement (
281- project : Project ,
282- pathToNPM : String ,
283- requirement : PackageData ,
284- ) {
262+ private fun PackageDataService.checkAndInstallRequirements (project : Project ): Boolean {
263+ val missingPackages = jsPackagesList.filterNot { this .findPackage(it) }
264+ if (missingPackages.isEmpty()) return true
285265 val message = """
286- Requirement is not installed:
287- ${requirement. packageName}
288- Install it ?
266+ Requirements are not installed:
267+ ${missingPackages.joinToString { it. packageName } }
268+ Install them ?
289269 """ .trimIndent()
290270 val result = Messages .showOkCancelDialog(
291- project,
292- message,
293- " Requirement Missmatch Error" ,
294- " Install" ,
295- " Cancel" ,
296- null
271+ project, message, " Requirements Missmatch Error" , " Install" , " Cancel" , null
297272 )
298273
299274 if (result == Messages .CANCEL )
300- return
275+ return false
301276
302- val (_, errorText) = requirement.installPackage(project.basePath!! , pathToNPM)
303-
304- if (errorText.isNotEmpty()) {
277+ try {
278+ val (_, errorText) = this .installMissingPackages(missingPackages)
279+ if (errorText.isNotEmpty()) {
280+ showErrorDialogLater(
281+ project,
282+ " Requirements installing failed with some reason:\n ${errorText} " ,
283+ " Failed to install requirements"
284+ )
285+ return false
286+ }
287+ return true
288+ } catch (_: TimeoutException ) {
305289 showErrorDialogLater(
306290 project,
307- " Requirements installing failed with some reason:\n ${errorText} " ,
308- " Requirements error"
291+ """
292+ Requirements installing failed due to the exceeded waiting time for the installation, check your internet connection.
293+
294+ Try to install missing npm packages manually:
295+ ${
296+ missingPackages.joinToString(separator = " \n " ) {
297+ " > npm install ${it.npmListFlag} ${it.packageName} "
298+ }
299+ }
300+ """ .trimIndent(),
301+ " Failed to install requirements"
309302 )
303+ return false
310304 }
311305}
0 commit comments