Kotlin Ultimate: Support Protractor run configurations for module directory
This commit is contained in:
@@ -37,7 +37,7 @@ dependencies {
|
||||
|
||||
compile(ideaUltimatePreloadedDeps("*.jar", subdir = "nodejs_plugin/NodeJS/lib"))
|
||||
compile(ideaUltimateSdkCoreDeps("annotations", "trove4j", "intellij-core"))
|
||||
compile(ideaUltimateSdkDeps("openapi", "idea", "util"))
|
||||
compile(ideaUltimateSdkDeps("openapi", "idea", "util", "jdom"))
|
||||
compile(ideaUltimatePluginDeps("*.jar", plugin = "CSS"))
|
||||
compile(ideaUltimatePluginDeps("*.jar", plugin = "DatabaseTools"))
|
||||
compile(ideaUltimatePluginDeps("*.jar", plugin = "JavaEE"))
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<idea-plugin>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.nodejs.KotlinMochaRunConfigurationProducer"/>
|
||||
<configurationType implementation="org.jetbrains.kotlin.idea.nodejs.protractor.KotlinProtractorConfigurationType"/>
|
||||
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.nodejs.mocha.KotlinMochaRunConfigurationProducer"/>
|
||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.nodejs.protractor.KotlinProtractorRunConfigurationProducer"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
|
||||
@@ -35,4 +35,4 @@ fun getJsClasspath(module: Module): List<String> {
|
||||
true
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
+20
-11
@@ -1,8 +1,23 @@
|
||||
package org.jetbrains.kotlin.idea.nodejs
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.nodejs.mocha
|
||||
|
||||
import com.intellij.execution.RunManager
|
||||
import com.intellij.execution.actions.ConfigurationContext
|
||||
import com.intellij.execution.configuration.EnvironmentVariablesData
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleUtilCore
|
||||
import com.intellij.openapi.project.Project
|
||||
@@ -13,14 +28,13 @@ import com.intellij.openapi.vfs.VfsUtilCore
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiDirectory
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.impl.file.PsiJavaDirectoryImpl
|
||||
import com.intellij.psi.util.PsiUtilCore
|
||||
import com.intellij.util.SmartList
|
||||
import com.intellij.util.containers.SmartHashSet
|
||||
import com.jetbrains.nodejs.mocha.MochaUtil
|
||||
import com.jetbrains.nodejs.mocha.execution.*
|
||||
import org.jetbrains.kotlin.idea.js.getJsClasspath
|
||||
import org.jetbrains.kotlin.idea.js.getJsOutputFilePath
|
||||
import org.jetbrains.kotlin.idea.nodejs.getNodeJsEnvironmentVars
|
||||
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
|
||||
import org.jetbrains.kotlin.idea.util.projectStructure.getModuleDir
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatform
|
||||
@@ -30,7 +44,6 @@ import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||
import java.io.File
|
||||
|
||||
class KotlinMochaRunConfigurationProducer : MochaRunConfigurationProducer() {
|
||||
private data class TestElementInfo(val runSettings: MochaRunSettings, val enclosingTestElement: PsiElement)
|
||||
@@ -80,7 +93,7 @@ class KotlinMochaRunConfigurationProducer : MochaRunConfigurationProducer() {
|
||||
}
|
||||
|
||||
private fun createSuiteOrTestData(element: PsiElement, module: Module): TestElementPath? {
|
||||
if (element is PsiDirectory && module.getModuleDir() == (element as PsiJavaDirectoryImpl).virtualFile.path) {
|
||||
if (element is PsiDirectory && module.getModuleDir() == element.virtualFile.path) {
|
||||
return TestElementPath.BySingleFile
|
||||
}
|
||||
|
||||
@@ -133,11 +146,7 @@ class KotlinMochaRunConfigurationProducer : MochaRunConfigurationProducer() {
|
||||
}
|
||||
}
|
||||
|
||||
val nodeJsClasspath = getJsClasspath(module).joinToString(File.pathSeparator) {
|
||||
val basePath = project.basePath ?: return@joinToString it
|
||||
FileUtil.getRelativePath(basePath, it, '/') ?: it
|
||||
}
|
||||
builder.setEnvData(EnvironmentVariablesData.create(mapOf("NODE_PATH" to nodeJsClasspath), true))
|
||||
builder.setEnvData(module.getNodeJsEnvironmentVars())
|
||||
|
||||
return TestElementInfo(builder.build(), element)
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.nodejs
|
||||
|
||||
import com.intellij.execution.configuration.EnvironmentVariablesData
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.kotlin.idea.js.getJsClasspath
|
||||
import java.io.File
|
||||
|
||||
const val NODE_PATH_VAR = "NODE_PATH"
|
||||
|
||||
fun Module.getNodeJsEnvironmentVars(): EnvironmentVariablesData {
|
||||
val nodeJsClasspath = getJsClasspath(this).joinToString(File.pathSeparator) {
|
||||
val basePath = project.basePath ?: return@joinToString it
|
||||
FileUtil.getRelativePath(basePath, it, '/') ?: it
|
||||
}
|
||||
return EnvironmentVariablesData.create(mapOf(NODE_PATH_VAR to nodeJsClasspath), true)
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.nodejs.protractor
|
||||
|
||||
import com.intellij.execution.configuration.ConfigurationFactoryEx
|
||||
import com.intellij.execution.configurations.ConfigurationFactory
|
||||
import com.intellij.execution.configurations.ConfigurationTypeBase
|
||||
import com.intellij.execution.configurations.ConfigurationTypeUtil
|
||||
import com.intellij.openapi.project.Project
|
||||
import icons.JavaScriptLanguageIcons
|
||||
|
||||
class KotlinProtractorConfigurationType : ConfigurationTypeBase(
|
||||
"KotlinJavaScriptTestRunnerProtractor",
|
||||
"Protractor",
|
||||
NAME,
|
||||
JavaScriptLanguageIcons.Protractor.Protractor
|
||||
) {
|
||||
init {
|
||||
addFactory(object : ConfigurationFactoryEx<KotlinProtractorRunConfiguration>(this) {
|
||||
override fun createTemplateConfiguration(project: Project) = KotlinProtractorRunConfiguration(project, this, NAME)
|
||||
|
||||
override fun isConfigurationSingletonByDefault() = true
|
||||
|
||||
override fun canConfigurationBeSingleton() = false
|
||||
|
||||
override fun onNewConfigurationCreated(configuration: KotlinProtractorRunConfiguration) = configuration.initialize()
|
||||
})
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val NAME = "Protractor"
|
||||
|
||||
fun getInstance() = ConfigurationTypeUtil.findConfigurationType(KotlinProtractorConfigurationType::class.java)
|
||||
|
||||
val factory: ConfigurationFactory
|
||||
get() = getInstance().configurationFactories.first()
|
||||
}
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.nodejs.protractor
|
||||
|
||||
import com.intellij.execution.Executor
|
||||
import com.intellij.execution.configurations.ConfigurationFactory
|
||||
import com.intellij.execution.configurations.LocatableConfigurationBase
|
||||
import com.intellij.execution.configurations.RuntimeConfigurationError
|
||||
import com.intellij.execution.runners.ExecutionEnvironment
|
||||
import com.intellij.javascript.nodejs.interpreter.local.NodeJsLocalInterpreter
|
||||
import com.intellij.javascript.nodejs.util.NodePackage
|
||||
import com.intellij.javascript.protractor.ProtractorUtil
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.util.PathUtil
|
||||
import org.jdom.Element
|
||||
import java.io.File
|
||||
|
||||
// Based on com.intellij.javascript.protractor.ProtractorRunConfiguration
|
||||
class KotlinProtractorRunConfiguration(
|
||||
project: Project,
|
||||
factory: ConfigurationFactory,
|
||||
name: String
|
||||
) : LocatableConfigurationBase(project, factory, name) {
|
||||
var runSettings = KotlinProtractorRunSettings()
|
||||
|
||||
val protractorPackage: NodePackage
|
||||
get() {
|
||||
val project = project
|
||||
val interpreter = runSettings.interpreterRef.resolve(project)
|
||||
return ProtractorUtil.getProtractorPackage(project, null, interpreter, true)
|
||||
}
|
||||
|
||||
override fun getState(executor: Executor, environment: ExecutionEnvironment) =
|
||||
KotlinProtractorRunState(this, environment, protractorPackage)
|
||||
|
||||
override fun getConfigurationEditor() = KotlinProtractorRunConfigurationEditor(project)
|
||||
|
||||
override fun readExternal(element: Element) {
|
||||
super.readExternal(element)
|
||||
runSettings = KotlinProtractorRunSettings.readFromXML(element)
|
||||
}
|
||||
|
||||
override fun writeExternal(element: Element) {
|
||||
super.writeExternal(element)
|
||||
runSettings.writeToXML(element)
|
||||
}
|
||||
|
||||
fun initialize() {
|
||||
setNameChangedByUser(false)
|
||||
}
|
||||
|
||||
override fun checkConfiguration() {
|
||||
val isOptionalConfig = runSettings.testFileSystemDependentPath.isNotBlank() || runSettings.seleniumAddress.isNotBlank()
|
||||
if (isOptionalConfig) {
|
||||
validatePath("test file", runSettings.testFileSystemDependentPath, true, false)
|
||||
if (runSettings.seleniumAddress.isBlank()) {
|
||||
throw RuntimeConfigurationError("Unspecified Selenium address")
|
||||
}
|
||||
}
|
||||
if (!isOptionalConfig || runSettings.configFileSystemDependentPath.isNotBlank()) {
|
||||
validatePath("configuration file", runSettings.configFileSystemDependentPath, true, false)
|
||||
}
|
||||
|
||||
val interpreter = runSettings.interpreterRef.resolve(project)
|
||||
NodeJsLocalInterpreter.checkForRunConfiguration(interpreter)
|
||||
|
||||
validatePath("protractor package", protractorPackage.systemDependentPath, true, true)
|
||||
}
|
||||
|
||||
override fun suggestedName(): String? {
|
||||
val name = PathUtil.getFileName(runSettings.testFileSystemDependentPath)
|
||||
return if (name.isNotBlank()) name else null
|
||||
}
|
||||
|
||||
private fun validatePath(name: String,
|
||||
path: String?,
|
||||
shouldBeAbsolute: Boolean,
|
||||
shouldBeDirectory: Boolean
|
||||
) {
|
||||
if (path.isNullOrBlank()) throw RuntimeConfigurationError("Unspecified " + name)
|
||||
|
||||
val file = File(path!!)
|
||||
|
||||
if (shouldBeAbsolute && !file.isAbsolute) throw RuntimeConfigurationError("No such " + name)
|
||||
|
||||
val exists = if (shouldBeDirectory) file.isDirectory else file.isFile
|
||||
if (!exists) throw RuntimeConfigurationError("No such " + name)
|
||||
}
|
||||
}
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.nodejs.protractor
|
||||
|
||||
import com.intellij.execution.configuration.EnvironmentVariablesTextFieldWithBrowseButton
|
||||
import com.intellij.javascript.nodejs.interpreter.NodeJsInterpreterField
|
||||
import com.intellij.javascript.nodejs.util.NodePackageField
|
||||
import com.intellij.javascript.protractor.ProtractorUtil
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory
|
||||
import com.intellij.openapi.options.SettingsEditor
|
||||
import com.intellij.openapi.options.ex.SingleConfigurableEditor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.DialogWrapper
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.ui.RawCommandLineEditor
|
||||
import com.intellij.ui.TextFieldWithHistoryWithBrowseButton
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import com.intellij.util.ui.FormBuilder
|
||||
import com.intellij.util.ui.JBUI
|
||||
import com.intellij.util.ui.SwingHelper
|
||||
|
||||
import javax.swing.*
|
||||
import java.util.Collections
|
||||
|
||||
// Based com.intellij.javascript.protractor.ProtractorRunConfigurationEditor
|
||||
class KotlinProtractorRunConfigurationEditor(private val myProject: Project) : SettingsEditor<KotlinProtractorRunConfiguration>() {
|
||||
private val testFilePathTextFieldWithBrowseButton: TextFieldWithHistoryWithBrowseButton
|
||||
private val seleniumAddressTextField: JTextField
|
||||
private val extraOptionsEditor: RawCommandLineEditor
|
||||
private val configPathTextFieldWithBrowseButton: TextFieldWithHistoryWithBrowseButton
|
||||
private val interpreterField: NodeJsInterpreterField
|
||||
private val protractorPackageField: NodePackageField
|
||||
private val envVarsComponent: EnvironmentVariablesTextFieldWithBrowseButton
|
||||
private val panel: JPanel
|
||||
|
||||
init {
|
||||
testFilePathTextFieldWithBrowseButton = createTestFileTextField(myProject)
|
||||
seleniumAddressTextField = JTextField()
|
||||
extraOptionsEditor = RawCommandLineEditor().apply { dialogCaption = "Extra Protractor Options" }
|
||||
configPathTextFieldWithBrowseButton = createConfigurationFileTextField(myProject)
|
||||
interpreterField = NodeJsInterpreterField(myProject, false)
|
||||
protractorPackageField = NodePackageField(myProject, ProtractorUtil.PACKAGE_NAME) { interpreterField.interpreter }
|
||||
envVarsComponent = EnvironmentVariablesTextFieldWithBrowseButton()
|
||||
panel = FormBuilder()
|
||||
.setAlignLabelOnRight(false)
|
||||
.addLabeledComponent("&Test file:", testFilePathTextFieldWithBrowseButton)
|
||||
.addLabeledComponent("&Selenium address:", seleniumAddressTextField)
|
||||
.addLabeledComponent("E&xtra Protractor options:", extraOptionsEditor)
|
||||
.addComponent(JSeparator(), JBUI.scale(8))
|
||||
.addLabeledComponent("&Configuration file:", configPathTextFieldWithBrowseButton)
|
||||
.addComponent(JSeparator(), JBUI.scale(8))
|
||||
.addLabeledComponent("Node &interpreter:", interpreterField, JBUI.scale(8))
|
||||
.addLabeledComponent("&Protractor package:", protractorPackageField)
|
||||
.addLabeledComponent("&Environment variables:", envVarsComponent)
|
||||
.panel
|
||||
}
|
||||
|
||||
private fun createConfigurationFileTextField(project: Project) = TextFieldWithHistoryWithBrowseButton().apply {
|
||||
val textFieldWithHistory = childComponent
|
||||
textFieldWithHistory.setHistorySize(-1)
|
||||
textFieldWithHistory.setMinimumAndPreferredWidth(0)
|
||||
SwingHelper.addHistoryOnExpansion(textFieldWithHistory) {
|
||||
val newFiles = ProtractorUtil.listPossibleConfigFilesInProject(project)
|
||||
val newFilePaths = ContainerUtil.map(newFiles) { file -> FileUtil.toSystemDependentName(file.path) }
|
||||
Collections.sort(newFilePaths)
|
||||
newFilePaths
|
||||
}
|
||||
|
||||
SwingHelper.installFileCompletionAndBrowseDialog(
|
||||
project,
|
||||
this,
|
||||
"Select Protractor Configuration File",
|
||||
FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor()
|
||||
)
|
||||
}
|
||||
|
||||
private fun createTestFileTextField(project: Project) = TextFieldWithHistoryWithBrowseButton().apply {
|
||||
val textFieldWithHistory = childComponent
|
||||
textFieldWithHistory.setHistorySize(-1)
|
||||
textFieldWithHistory.setMinimumAndPreferredWidth(0)
|
||||
|
||||
SwingHelper.installFileCompletionAndBrowseDialog(
|
||||
project,
|
||||
this,
|
||||
"Select Protractor Configuration File",
|
||||
FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor()
|
||||
)
|
||||
}
|
||||
|
||||
override fun resetEditorFrom(runConfiguration: KotlinProtractorRunConfiguration) {
|
||||
with(runConfiguration.runSettings) {
|
||||
testFilePathTextFieldWithBrowseButton.setTextAndAddToHistory(testFileSystemDependentPath)
|
||||
seleniumAddressTextField.text = seleniumAddress
|
||||
extraOptionsEditor.text = extraOptions
|
||||
configPathTextFieldWithBrowseButton.setTextAndAddToHistory(configFileSystemDependentPath)
|
||||
interpreterField.interpreterRef = interpreterRef
|
||||
protractorPackageField.selected = runConfiguration.protractorPackage
|
||||
envVarsComponent.data = envData
|
||||
}
|
||||
updatePreferredWidth()
|
||||
}
|
||||
|
||||
private fun updatePreferredWidth() {
|
||||
val dialogWrapper = DialogWrapper.findInstance(panel)
|
||||
if (dialogWrapper is SingleConfigurableEditor) {
|
||||
// dialog for single run configuration
|
||||
interpreterField.setPreferredWidthToFitText()
|
||||
protractorPackageField.setPreferredWidthToFitText()
|
||||
SwingHelper.setPreferredWidthToFitText(testFilePathTextFieldWithBrowseButton)
|
||||
SwingHelper.setPreferredWidthToFitText(seleniumAddressTextField)
|
||||
SwingHelper.setPreferredWidthToFitText(configPathTextFieldWithBrowseButton)
|
||||
ApplicationManager.getApplication().invokeLater { SwingHelper.adjustDialogSizeToFitPreferredSize(dialogWrapper) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun applyEditorTo(runConfiguration: KotlinProtractorRunConfiguration) {
|
||||
ProtractorUtil.setProtractorPackage(myProject, protractorPackageField.selected)
|
||||
runConfiguration.runSettings = runConfiguration.runSettings.copy(
|
||||
interpreterRef = interpreterField.interpreterRef,
|
||||
configFilePath = configPathTextFieldWithBrowseButton.text,
|
||||
testFilePath = testFilePathTextFieldWithBrowseButton.text,
|
||||
seleniumAddress = seleniumAddressTextField.text,
|
||||
extraOptions = extraOptionsEditor.text,
|
||||
envData = envVarsComponent.data
|
||||
)
|
||||
}
|
||||
|
||||
override fun createEditor() = panel
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.nodejs.protractor
|
||||
|
||||
import com.intellij.execution.actions.CompatibleRunConfigurationProducer
|
||||
import com.intellij.execution.actions.ConfigurationContext
|
||||
import com.intellij.openapi.module.ModuleUtilCore
|
||||
import com.intellij.openapi.util.Ref
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.psi.PsiDirectory
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.js.getJsOutputFilePath
|
||||
import org.jetbrains.kotlin.idea.nodejs.getNodeJsEnvironmentVars
|
||||
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
|
||||
import org.jetbrains.kotlin.idea.util.projectStructure.getModuleDir
|
||||
import org.jetbrains.kotlin.idea.util.projectStructure.module
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatform
|
||||
|
||||
class KotlinProtractorRunConfigurationProducer :
|
||||
CompatibleRunConfigurationProducer<KotlinProtractorRunConfiguration>(KotlinProtractorConfigurationType.getInstance()) {
|
||||
override fun isConfigurationFromCompatibleContext(
|
||||
configuration: KotlinProtractorRunConfiguration,
|
||||
context: ConfigurationContext
|
||||
): Boolean {
|
||||
val contextPsi = context.psiLocation ?: return false
|
||||
val module = contextPsi.module ?: return false
|
||||
val testFilePath = getJsOutputFilePath(module, isTests = true, isMeta = false) ?: return false
|
||||
return configuration.runSettings.testFileSystemDependentPath == FileUtil.toSystemDependentName(testFilePath)
|
||||
}
|
||||
|
||||
override fun setupConfigurationFromCompatibleContext(
|
||||
configuration: KotlinProtractorRunConfiguration,
|
||||
context: ConfigurationContext,
|
||||
sourceElement: Ref<PsiElement>
|
||||
): Boolean {
|
||||
val element = context.psiLocation ?: return false
|
||||
val module = ModuleUtilCore.findModuleForPsiElement(element) ?: return false
|
||||
if (element !is PsiDirectory || module.getModuleDir() != element.virtualFile.path) return false
|
||||
if (TargetPlatformDetector.getPlatform(module) !is JsPlatform) return false
|
||||
val testFilePath = getJsOutputFilePath(module, true, false) ?: return false
|
||||
|
||||
sourceElement.set(element)
|
||||
configuration.runSettings = configuration.runSettings.copy(
|
||||
testFilePath = testFilePath,
|
||||
envData = module.getNodeJsEnvironmentVars()
|
||||
)
|
||||
configuration.name = configuration.suggestedName()
|
||||
return true
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.nodejs.protractor
|
||||
|
||||
import com.intellij.execution.configuration.EnvironmentVariablesData
|
||||
import com.intellij.javascript.nodejs.interpreter.NodeJsInterpreterRef
|
||||
import com.intellij.openapi.util.JDOMExternalizerUtil.*
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import org.jdom.Element
|
||||
|
||||
data class KotlinProtractorRunSettings(
|
||||
val interpreterRef: NodeJsInterpreterRef = NodeJsInterpreterRef.createProjectRef(),
|
||||
private val configFilePath: String = "",
|
||||
private val testFilePath: String = "",
|
||||
val seleniumAddress: String = "",
|
||||
val extraOptions: String = "",
|
||||
val envData: EnvironmentVariablesData = EnvironmentVariablesData.DEFAULT
|
||||
) {
|
||||
val configFileSystemDependentPath get() = FileUtil.toSystemDependentName(configFilePath)
|
||||
val testFileSystemDependentPath get() = FileUtil.toSystemDependentName(testFilePath)
|
||||
|
||||
fun writeToXML(element: Element) {
|
||||
addElementWithValueAttribute(element, "config-file", FileUtil.toSystemIndependentName(configFileSystemDependentPath))
|
||||
addElementWithValueAttribute(element, "test-file", FileUtil.toSystemIndependentName(testFileSystemDependentPath))
|
||||
addElementWithValueAttribute(element, "selenium-address", seleniumAddress)
|
||||
addElementWithValueAttribute(element, "extra-protractor-options", extraOptions)
|
||||
addElementWithValueAttribute(element, "node-interpreter", interpreterRef.referenceName)
|
||||
envData.writeExternal(element)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun readFromXML(element: Element): KotlinProtractorRunSettings {
|
||||
val configFilePath = getFirstChildValueAttribute(element, "config-file")
|
||||
val testFilePath = getFirstChildValueAttribute(element, "test-file")
|
||||
val seleniumAddress = getFirstChildValueAttribute(element, "selenium-address")
|
||||
val extraOptions = getFirstChildValueAttribute(element, "extra-protractor-options")
|
||||
val interpreterRefName = getFirstChildValueAttribute(element, "node-interpreter")
|
||||
val envData = EnvironmentVariablesData.readExternal(element)
|
||||
return KotlinProtractorRunSettings(
|
||||
NodeJsInterpreterRef.create(interpreterRefName ?: "project"),
|
||||
configFilePath ?: "",
|
||||
testFilePath ?: "",
|
||||
seleniumAddress ?: "",
|
||||
extraOptions ?: "",
|
||||
envData
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.nodejs.protractor
|
||||
|
||||
import com.intellij.execution.DefaultExecutionResult
|
||||
import com.intellij.execution.ExecutionException
|
||||
import com.intellij.execution.ExecutionResult
|
||||
import com.intellij.execution.Executor
|
||||
import com.intellij.execution.configurations.GeneralCommandLine
|
||||
import com.intellij.execution.configurations.RunProfileState
|
||||
import com.intellij.execution.process.ProcessHandler
|
||||
import com.intellij.execution.process.ProcessTerminatedListener
|
||||
import com.intellij.execution.runners.ExecutionEnvironment
|
||||
import com.intellij.execution.testframework.TestConsoleProperties
|
||||
import com.intellij.execution.testframework.autotest.ToggleAutoTestAction
|
||||
import com.intellij.execution.testframework.sm.SMCustomMessagesParsing
|
||||
import com.intellij.execution.testframework.sm.SMTestRunnerConnectionUtil
|
||||
import com.intellij.execution.testframework.sm.runner.SMTRunnerConsoleProperties
|
||||
import com.intellij.execution.testframework.sm.runner.SMTestLocator
|
||||
import com.intellij.execution.ui.ConsoleView
|
||||
import com.intellij.javascript.HelperFilesLocator
|
||||
import com.intellij.javascript.nodejs.NodeCommandLineUtil
|
||||
import com.intellij.javascript.nodejs.debug.NodeLocalDebugRunProfileState
|
||||
import com.intellij.javascript.nodejs.interpreter.local.NodeJsLocalInterpreter
|
||||
import com.intellij.javascript.nodejs.util.NodePackage
|
||||
import com.intellij.javascript.protractor.ProtractorConsoleFilter
|
||||
import com.intellij.javascript.protractor.ProtractorOutputToGeneralTestEventsConverter
|
||||
import com.intellij.javascript.protractor.ProtractorUtil
|
||||
import com.intellij.javascript.testFramework.navigation.JSTestLocationProvider
|
||||
import com.intellij.lang.javascript.buildTools.base.JsbtUtil
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.util.PathUtil
|
||||
import com.intellij.util.execution.ParametersListUtil
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
class KotlinProtractorRunState(
|
||||
private val runConfiguration: KotlinProtractorRunConfiguration,
|
||||
private val environment: ExecutionEnvironment,
|
||||
private val protractorPackage: NodePackage
|
||||
) : RunProfileState, NodeLocalDebugRunProfileState {
|
||||
companion object {
|
||||
val FRAMEWORK_NAME = "KotlinProtractorJavaScriptTestRunner"
|
||||
private val INTELLIJ_CONFIG_FILE_PATH = "protractor-intellij/lib/protractor-intellij-config.js"
|
||||
}
|
||||
|
||||
private val project = runConfiguration.project
|
||||
private val runSettings = runConfiguration.runSettings
|
||||
|
||||
override fun execute(debugPort: Int): ExecutionResult {
|
||||
val interpreter = runSettings.interpreterRef.resolveAsLocal(project)
|
||||
val commandLine = createCommandLine(interpreter, debugPort)
|
||||
val processHandler = NodeCommandLineUtil.createProcessHandler(commandLine, false)
|
||||
val consoleView = createSmtRunnerConsoleView(commandLine.workDirectory)
|
||||
ProcessTerminatedListener.attach(processHandler)
|
||||
consoleView.attachToProcess(processHandler)
|
||||
foldCommandLine(consoleView, processHandler)
|
||||
val executionResult = DefaultExecutionResult(consoleView, processHandler)
|
||||
executionResult.setRestartActions(ToggleAutoTestAction())
|
||||
return executionResult
|
||||
}
|
||||
|
||||
private fun createSmtRunnerConsoleView(workingDirectory: File?): ConsoleView {
|
||||
val testConsoleProperties = ProtractorConsoleProperties(runConfiguration, environment.executor, JSTestLocationProvider())
|
||||
val consoleView = SMTestRunnerConnectionUtil.createConsole(FRAMEWORK_NAME, testConsoleProperties)
|
||||
consoleView.addMessageFilter(ProtractorConsoleFilter(project, workingDirectory))
|
||||
Disposer.register(environment, consoleView)
|
||||
return consoleView
|
||||
}
|
||||
|
||||
override fun foldCommandLine(consoleView: ConsoleView, processHandler: ProcessHandler) {
|
||||
val configFileName = PathUtil.getFileName(runSettings.configFileSystemDependentPath)
|
||||
val testFileName = PathUtil.getFileName(runSettings.testFileSystemDependentPath)
|
||||
val seleniumAddress = runSettings.seleniumAddress
|
||||
val parameters = ArrayList<String>().apply {
|
||||
add("protractor")
|
||||
if (configFileName.isNotBlank()) {
|
||||
add(configFileName)
|
||||
}
|
||||
if (testFileName.isNotBlank()) {
|
||||
add("--specs=$testFileName")
|
||||
}
|
||||
if (seleniumAddress.isNotBlank()) {
|
||||
add("--seleniumAddress=$seleniumAddress")
|
||||
}
|
||||
addAll(ParametersListUtil.parse(runSettings.extraOptions.trim()))
|
||||
}
|
||||
val foldedCommandLine = ParametersListUtil.join(parameters)
|
||||
JsbtUtil.foldCommandLine(consoleView, processHandler, foldedCommandLine)
|
||||
}
|
||||
|
||||
private fun createCommandLine(interpreter: NodeJsLocalInterpreter, debugPort: Int): GeneralCommandLine {
|
||||
val commandLine = GeneralCommandLine().apply { charset = StandardCharsets.UTF_8 }
|
||||
|
||||
runSettings.envData.configureCommandLine(commandLine, true)
|
||||
|
||||
val originalConfigFilePath = runSettings.configFileSystemDependentPath
|
||||
val testFilePath = runSettings.testFileSystemDependentPath
|
||||
val seleniumAddress = runSettings.seleniumAddress
|
||||
val withConfigFile = originalConfigFilePath.isNotBlank()
|
||||
commandLine.setWorkDirectory(project.basePath)
|
||||
|
||||
commandLine.exePath = interpreter.interpreterSystemDependentPath
|
||||
NodeCommandLineUtil.addNodeOptionsForDebugging(commandLine, emptyList(), debugPort, true, interpreter, true)
|
||||
NodeCommandLineUtil.configureUsefulEnvironment(commandLine)
|
||||
commandLine.addParameter(ProtractorUtil.getProtractorMainJsFile(protractorPackage).absolutePath)
|
||||
|
||||
val intellijConfigFile = try {
|
||||
HelperFilesLocator.getFileRelativeToHelpersDir(INTELLIJ_CONFIG_FILE_PATH)
|
||||
}
|
||||
catch (e: IOException) {
|
||||
throw ExecutionException("Cannot locate wrapper config file", e)
|
||||
}
|
||||
|
||||
commandLine.addParameter(intellijConfigFile.absolutePath)
|
||||
|
||||
val actualConfigFilePath = if (withConfigFile) {
|
||||
originalConfigFilePath
|
||||
}
|
||||
else {
|
||||
val tempConfigFile = File.createTempFile("protractor", "conf.js")
|
||||
tempConfigFile.writeText("exports.config = {}")
|
||||
tempConfigFile.absolutePath
|
||||
}
|
||||
|
||||
commandLine.addParameter("--intellijOriginalConfigFile=$actualConfigFilePath")
|
||||
|
||||
if (testFilePath.isNotBlank()) {
|
||||
commandLine.addParameter("--specs=$testFilePath")
|
||||
}
|
||||
|
||||
if (seleniumAddress.isNotBlank()) {
|
||||
commandLine.addParameter("--seleniumAddress=$seleniumAddress")
|
||||
}
|
||||
|
||||
commandLine.addParameters(ParametersListUtil.parse(runSettings.extraOptions.trim()))
|
||||
|
||||
commandLine.addParameter("--disableChecks")
|
||||
|
||||
return commandLine
|
||||
}
|
||||
|
||||
private class ProtractorConsoleProperties(
|
||||
configuration: KotlinProtractorRunConfiguration,
|
||||
executor: Executor,
|
||||
private val myLocator: SMTestLocator
|
||||
) : SMTRunnerConsoleProperties(configuration, FRAMEWORK_NAME, executor), SMCustomMessagesParsing {
|
||||
init {
|
||||
isUsePredefinedMessageFilter = false
|
||||
setIfUndefined(TestConsoleProperties.HIDE_PASSED_TESTS, false)
|
||||
setIfUndefined(TestConsoleProperties.HIDE_IGNORED_TEST, true)
|
||||
setIfUndefined(TestConsoleProperties.SCROLL_TO_SOURCE, true)
|
||||
setIfUndefined(TestConsoleProperties.SELECT_FIRST_DEFECT, true)
|
||||
isIdBasedTestTree = true
|
||||
isPrintTestingStartedTime = false
|
||||
}
|
||||
|
||||
override fun getTestLocator() = myLocator
|
||||
|
||||
override fun createTestEventsConverter(testFrameworkName: String, consoleProperties: TestConsoleProperties) =
|
||||
ProtractorOutputToGeneralTestEventsConverter(testFrameworkName, consoleProperties.isEditable)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user