package com.intellij.javascript.karma.execution;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.process.*;
import com.intellij.execution.testframework.TestConsoleProperties;
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.testframework.sm.runner.TestProxyFilterProvider;
import com.intellij.execution.testframework.sm.runner.ui.SMTRunnerConsoleView;
import com.intellij.javascript.karma.KarmaConfig;
import com.intellij.javascript.karma.scope.KarmaScopeKind;
import com.intellij.javascript.karma.server.KarmaServer;
import com.intellij.javascript.karma.server.KarmaServerTerminatedListener;
import com.intellij.javascript.karma.tree.KarmaTestProxyFilterProvider;
import com.intellij.javascript.nodejs.interpreter.local.NodeJsLocalInterpreter;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
public class KarmaExecutionSession {
private static final String FRAMEWORK_NAME = "KarmaJavaScriptTestRunner";
private final Project myProject;
private final KarmaRunConfiguration myRunConfiguration;
private final Executor myExecutor;
private final KarmaServer myKarmaServer;
private final KarmaRunSettings myRunSettings;
private final SMTRunnerConsoleView mySmtConsoleView;
private final ProcessHandler myProcessHandler;
private final KarmaExecutionType myExecutionType;
public KarmaExecutionSession(@NotNull Project project,
@NotNull KarmaRunConfiguration runConfiguration,
@NotNull Executor executor,
@NotNull KarmaServer karmaServer,
@NotNull KarmaRunSettings runSettings,
@NotNull KarmaExecutionType executionType) throws ExecutionException {
myProject = project;
myRunConfiguration = runConfiguration;
myExecutor = executor;
myKarmaServer = karmaServer;
myRunSettings = runSettings;
mySmtConsoleView = createSMTRunnerConsoleView();
myExecutionType = executionType;
myProcessHandler = createProcessHandler(karmaServer);
}
@NotNull
private SMTRunnerConsoleView createSMTRunnerConsoleView() {
KarmaTestProxyFilterProvider filterProvider = new KarmaTestProxyFilterProvider(myProject, myKarmaServer);
TestConsoleProperties testConsoleProperties = new KarmaConsoleProperties(myRunConfiguration, myExecutor, filterProvider);
KarmaConsoleView consoleView = new KarmaConsoleView(testConsoleProperties, myKarmaServer, this);
Disposer.register(myProject, consoleView);
SMTestRunnerConnectionUtil.initConsoleView(consoleView, FRAMEWORK_NAME);
return consoleView;
}
public boolean isDebug() {
return myExecutionType == KarmaExecutionType.DEBUG;
}
@NotNull
private ProcessHandler createProcessHandler(@NotNull final KarmaServer server) throws ExecutionException {
final File clientAppFile;
try {
clientAppFile = server.getKarmaJsSourcesLocator().getClientAppFile();
}
catch (IOException e) {
throw new ExecutionException("Can't find karma-intellij test runner", e);
}
if (server.areBrowsersReady()) {
return createOSProcessHandler(server, clientAppFile);
}
final NopProcessHandler nopProcessHandler = new NopProcessHandler();
terminateOnServerShutdown(server, nopProcessHandler);
return nopProcessHandler;
}
private static void terminateOnServerShutdown(@NotNull final KarmaServer server, @NotNull final ProcessHandler processHandler) {
final KarmaServerTerminatedListener terminationCallback = new KarmaServerTerminatedListener() {
@Override
public void onTerminated(int exitCode) {
processHandler.destroyProcess();
}
};
server.onTerminated(terminationCallback);
processHandler.addProcessListener(new ProcessAdapter() {
@Override
public void processTerminated(ProcessEvent event) {
server.removeTerminatedListener(terminationCallback);
}
});
}
@NotNull
private OSProcessHandler createOSProcessHandler(@NotNull KarmaServer server,
@NotNull File clientAppFile) throws ExecutionException {
NodeJsLocalInterpreter interpreter = myRunSettings.getInterpreterRef().resolveAsLocal(myProject);
GeneralCommandLine commandLine = createCommandLine(interpreter, server.getServerPort(), server.getKarmaConfig(), clientAppFile);
OSProcessHandler processHandler = new KillableColoredProcessHandler(commandLine);
server.getRestarter().onRunnerExecutionStarted(processHandler);
ProcessTerminatedListener.attach(processHandler);
mySmtConsoleView.attachToProcess(processHandler);
return processHandler;
}
@NotNull
private GeneralCommandLine createCommandLine(@NotNull NodeJsLocalInterpreter interpreter,
int serverPort,
@Nullable KarmaConfig config,
@NotNull File clientAppFile) {
GeneralCommandLine commandLine = new GeneralCommandLine();
File configFile = new File(myRunSettings.getConfigPath());
// looks like it should work with any working directory
commandLine.setWorkDirectory(configFile.getParentFile());
commandLine.setCharset(CharsetToolkit.UTF8_CHARSET);
commandLine.setExePath(interpreter.getInterpreterSystemDependentPath());
//NodeCommandLineUtil.addNodeOptionsForDebugging(commandLine, Collections.emptyList(), 5858, false, interpreter, true);
commandLine.addParameter(clientAppFile.getAbsolutePath());
commandLine.addParameter("--karmaPackageDir=" + myKarmaServer.getServerSettings().getKarmaPackage().getSystemDependentPath());
commandLine.addParameter("--serverPort=" + serverPort);
if (config != null) {
commandLine.addParameter("--urlRoot=" + config.getUrlRoot());
}
if (isDebug()) {
commandLine.addParameter("--debug=true");
}
if (myRunSettings.getScopeKind() == KarmaScopeKind.SUITE || myRunSettings.getScopeKind() == KarmaScopeKind.TEST) {
commandLine.addParameter("--testName=" + StringUtil.join(myRunSettings.getTestNames(), " "));
}
return commandLine;
}
@NotNull
public ProcessHandler getProcessHandler() {
return myProcessHandler;
}
@NotNull
public KarmaServer getKarmaServer() {
return myKarmaServer;
}
@NotNull
public SMTRunnerConsoleView getSmtConsoleView() {
return mySmtConsoleView;
}
private static class KarmaConsoleProperties extends SMTRunnerConsoleProperties {
private final KarmaTestProxyFilterProvider myFilterProvider;
public KarmaConsoleProperties(KarmaRunConfiguration configuration, Executor executor, KarmaTestProxyFilterProvider filterProvider) {
super(configuration, FRAMEWORK_NAME, executor);
myFilterProvider = filterProvider;
setUsePredefinedMessageFilter(true);
setIfUndefined(TestConsoleProperties.HIDE_PASSED_TESTS, false);
setIfUndefined(TestConsoleProperties.HIDE_IGNORED_TEST, true);
setIfUndefined(TestConsoleProperties.SCROLL_TO_SOURCE, true);
setIfUndefined(TestConsoleProperties.SELECT_FIRST_DEFECT, true);
setIdBasedTestTree(true);
setPrintTestingStartedTime(false);
}
@Override
public SMTestLocator getTestLocator() {
return KarmaTestLocationProvider.INSTANCE;
}
@Override
public TestProxyFilterProvider getFilterProvider() {
return myFilterProvider;
}
}
}