Skip to content

Commit

Permalink
Merge pull request #46 from nette-intellij/mn-added-line-markers
Browse files Browse the repository at this point in the history
Added run line markers
  • Loading branch information
mesour authored Apr 1, 2020
2 parents 33e074e + 189c23e commit 8c79318
Show file tree
Hide file tree
Showing 34 changed files with 900 additions and 118 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
.idea/
out/
intellij-nette-tester.iml
17 changes: 17 additions & 0 deletions intellij-nette-tester.iml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PLUGIN_MODULE" version="4">
<component name="DevKit.ModuleBuildProperties" url="file://$MODULE_DIR$/resources/META-INF/plugin.xml" />
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
<excludeFolder url="file://$MODULE_DIR$/out" isTestSource="false" generated="true" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" scope="PROVIDED" name="php-openapi" level="project" />
<orderEntry type="library" exported="" scope="PROVIDED" name="php" level="project" />
<orderEntry type="library" exported="" scope="PROVIDED" name="php-openapi-src" level="project" />
</component>
</module>
Binary file added intellij-nette-tester.jar
Binary file not shown.
67 changes: 46 additions & 21 deletions resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
@@ -1,35 +1,44 @@
<idea-plugin>
<id>cz.jiripudil.intellij.nette.tester</id>
<name>Nette Tester</name>
<version>2.0.0-beta.3</version>
<version>2.1.0</version>
<vendor email="[email protected]" url="https://jiripudil.cz">Jiří Pudil</vendor>
<resource-bundle>messages.TesterBundle</resource-bundle>

<description><![CDATA[
<a href="https://github.com/jiripudil/intellij-nette-tester">Github</a>
<a href="https://github.com/nette-intellij/intellij-nette-tester">Github</a>
<p>This plugin integrates <a href="https://tester.nette.org">Nette Tester</a>
into PhpStorm IDE.</p>
]]></description>

<change-notes><![CDATA[
<h2>2.1.0</h2>
<ul>
<li>Added run line markers to run TestCase or test methods</li>
<li>Added support for run configuration in Docker</li>
<li>Added support for Nette Tester 2.0</li>
<li>Fixed Compatibility with PHPStorm 2019.2 (<a href="https://github.com/nette-intellij/intellij-nette-tester/issues/43">#43</a>)</li>
<li>Fixed bug java.lang.NullPointerException on phpstorm startup (<a href="https://github.com/nette-intellij/intellij-nette-tester/issues/45">#45</a>)</li>
</ul>
<h2>2.0.0-beta.3</h2>
<ul>
<li>The Create Test dialog does not autoupdate the target namespace and directory if invoked from the directory context (<a href="https://github.com/jiripudil/intellij-nette-tester/issues/26">#26</a>)</li>
<li>Added some handy inspections that make sure all your tests are actually executed (<a href="https://github.com/jiripudil/intellij-nette-tester/issues/3">#3</a>, <a href="https://github.com/jiripudil/intellij-nette-tester/issues/32">#32</a>)</li>
<li>You can right-click a single test case file to run it (<a href="https://github.com/jiripudil/intellij-nette-tester/issues/23">#23</a>)</li>
<li>Added support for <code>nette/tester@dev-master</code> for the time being (<a href="https://github.com/jiripudil/intellij-nette-tester/issues/30">#30</a>)</li>
<li>Fixed: bootstrap relative path resolves correctly if the target directory does not exist (<a href="https://github.com/jiripudil/intellij-nette-tester/issues/25">#25</a>)</li>
<li>The Create Test dialog does not autoupdate the target namespace and directory if invoked from the directory context (<a href="https://github.com/nette-intellij/intellij-nette-tester/issues/26">#26</a>)</li>
<li>Added some handy inspections that make sure all your tests are actually executed (<a href="https://github.com/nette-intellij/intellij-nette-tester/issues/3">#3</a>, <a href="https://github.com/nette-intellij/intellij-nette-tester/issues/32">#32</a>)</li>
<li>You can right-click a single test case file to run it (<a href="https://github.com/nette-intellij/intellij-nette-tester/issues/23">#23</a>)</li>
<li>Added support for <code>nette/tester@dev-master</code> for the time being (<a href="https://github.com/nette-intellij/intellij-nette-tester/issues/30">#30</a>)</li>
<li>Fixed: bootstrap relative path resolves correctly if the target directory does not exist (<a href="https://github.com/nette-intellij/intellij-nette-tester/issues/25">#25</a>)</li>
<li>Fixed: comparison failure reporting was broken on Unix systems</li>
</ul>
<h2>2.0.0-beta.2</h2>
<p>I know I said this release branch would be feature-frozen, but... well... not just yet. I'm far too excited about bringing the new features to be able to postpone them. Semver doesn't play well with the plugin's distribution channel anyway. Here they come:</p>
<ul>
<li>In the project settings, you can configure the path to your bootstrap file; it is then automatically required in the created test files (see <a href="https://github.com/jiripudil/intellij-nette-tester/issues/20">#20</a> for instructions if it does not work right away)</li>
<li>You can now right-click a single <em>test method</em> to run or debug it in isolation (<a href="https://github.com/jiripudil/intellij-nette-tester/issues/9">#9</a>)</li>
<li>Fixed: OutputHandler now recognizes and correctly parses the diff command generated on Windows (<a href="https://github.com/jiripudil/intellij-nette-tester/issues/21">#21</a>)</li>
<li>Fixed: OutputHandler no longer reports unsuccessful builds as "terminated" (<a href="https://github.com/jiripudil/intellij-nette-tester/issues/22">#22</a>)</li>
<li>In the project settings, you can configure the path to your bootstrap file; it is then automatically required in the created test files (see <a href="https://github.com/nette-intellij/intellij-nette-tester/issues/20">#20</a> for instructions if it does not work right away)</li>
<li>You can now right-click a single <em>test method</em> to run or debug it in isolation (<a href="https://github.com/nette-intellij/intellij-nette-tester/issues/9">#9</a>)</li>
<li>Fixed: OutputHandler now recognizes and correctly parses the diff command generated on Windows (<a href="https://github.com/nette-intellij/intellij-nette-tester/issues/21">#21</a>)</li>
<li>Fixed: OutputHandler no longer reports unsuccessful builds as "terminated" (<a href="https://github.com/nette-intellij/intellij-nette-tester/issues/22">#22</a>)</li>
</ul>
<h2>2.0.0-beta.1</h2>
Expand Down Expand Up @@ -70,21 +79,27 @@
</ul>
]]></change-notes>

<idea-version since-build="141.0"/>
<idea-version since-build="183.2153.8"/>

<depends>com.intellij.modules.lang</depends>
<depends>com.jetbrains.php</depends>

<extensions defaultExtensionNs="com.intellij">
<configurationType implementation="cz.jiripudil.intellij.nette.tester.configuration.TesterRunConfigurationType"/>
<runConfigurationProducer implementation="cz.jiripudil.intellij.nette.tester.configuration.TesterRunConfigurationProducer"/>

<configurationType implementation="cz.jiripudil.intellij.nette.tester.configuration.TesterTestMethodRunConfigurationType"/>
<runConfigurationProducer implementation="cz.jiripudil.intellij.nette.tester.configuration.TesterTestMethodRunConfigurationProducer"/>

<analyzeStacktraceFilter implementation="cz.jiripudil.intellij.nette.tester.execution.TesterStackTraceFilter"/>

<runLineMarkerContributor language="PHP" implementationClass="cz.jiripudil.intellij.nette.tester.lineMarker.TesterRunLineMarkerProvider"/>
<runLineMarkerContributor language="PHP" implementationClass="cz.jiripudil.intellij.nette.tester.lineMarker.TesterMethodRunLineMarkerProvider"/>

<testFinder implementation="cz.jiripudil.intellij.nette.tester.TesterTestFinder"/>
<testCreator language="PHP" implementationClass="cz.jiripudil.intellij.nette.tester.codeGeneration.TesterTestCreator"/>
<internalFileTemplate name="Tester TestCase"/>
<backgroundPostStartupActivity implementation="cz.jiripudil.intellij.nette.tester.TesterPostStartupActivity"/>

<projectService serviceImplementation="cz.jiripudil.intellij.nette.tester.projectSettings.TesterProjectSettingsManager"/>
<projectConfigurable
Expand All @@ -93,11 +108,27 @@
id="cz.jiripudil.intellij.nette.tester.projectSettings.TesterConfigurable"
parentId="reference.webide.settings.project.settings.php"
groupWeight="25"
nonDefaultProject="true"
/>

<localInspection implementationClass="cz.jiripudil.intellij.nette.tester.inspections.TestFileNameInspection" groupName="Nette Tester" displayName="Test case files have correct names" enabledByDefault="true" level="ERROR"/>
<localInspection implementationClass="cz.jiripudil.intellij.nette.tester.inspections.TestCaseAnnotationInspection" groupName="Nette Tester" displayName="Test case has @testCase annotation" enabledByDefault="true" level="WARNING"/>
<localInspection implementationClass="cz.jiripudil.intellij.nette.tester.inspections.TestCaseIsRunInspection" groupName="Nette Tester" displayName="Test case is run" enabledByDefault="true" level="ERROR"/>
<localInspection
implementationClass="cz.jiripudil.intellij.nette.tester.inspections.TestFileNameInspection"
groupName="Nette tester"
displayName="Test case files have correct names"
enabledByDefault="true"
level="ERROR"/>
<localInspection
implementationClass="cz.jiripudil.intellij.nette.tester.inspections.TestCaseAnnotationInspection"
groupName="Nette tester"
displayName="Test case has @testCase annotation"
enabledByDefault="true"
level="WARNING"/>
<localInspection
implementationClass="cz.jiripudil.intellij.nette.tester.inspections.TestCaseIsRunInspection"
groupName="Nette tester"
displayName="Test case is run"
enabledByDefault="true"
level="ERROR"/>
</extensions>

<actions>
Expand All @@ -114,10 +145,4 @@
<add-to-group group-id="GenerateGroup" anchor="first"/>
</group>
</actions>

<application-components>
<component>
<implementation-class>cz.jiripudil.intellij.nette.tester.TesterTestCreatorEnabler</implementation-class>
</component>
</application-components>
</idea-plugin>
25 changes: 25 additions & 0 deletions resources/META-INF/pluginIcon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/icons/run.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/icons/runClass.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/icons/runMethod.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/icons/testConfig.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions resources/messages/TesterBundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
action.generateSetupMethod.name=TestCase setUp() method
action.generateSetupMethod.description=Creates a TestCase setUp() method

action.runTestAction.name=Run
action.createRunTestAction.name=Create

action.generateTeardownMethod.name=TestCase tearDown() method
action.generateTeardownMethod.description=Creates a TestCase tearDown() method

Expand Down Expand Up @@ -59,11 +62,24 @@ runConfiguration.editor.cli.title=Command Line
runConfiguration.editor.cli.interpreterOptions=Interpreter options:
runConfiguration.editor.cli.workingDirectory=Custom working directory:

runConfiguration.mainConfiguration.missing.title=Run configuration 'tester' missing
runConfiguration.mainConfiguration.missing.description=To use line markers, you need create run configuration named 'tester' with interpreter.

runConfiguration.mainConfiguration.invalid.title=Run configuration 'tester' is invalid
runConfiguration.mainConfiguration.invalid.description=To use line markers, you need valid run configuration named 'tester'.

runConfiguration.mainConfiguration.alreadyCreated.title=Run configuration already created
runConfiguration.mainConfiguration.alreadyCreated.description=Run configuration already exists. It can not be created again.

runConfiguration.mainConfiguration.created.title=Run configuration created
runConfiguration.mainConfiguration.created.description=Run configuration was successfully created.


# project settings

settings.defaultExtension=Default extension:
settings.bootstrapFile=Bootstrap file:
settings.testerVersion=Tester version:
settings.namespaceMappings.title=Namespace mappings
settings.namespaceMappings.noMappings=No mappings
settings.namespaceMappings.sourceNamespace=Source namespace
Expand Down
122 changes: 122 additions & 0 deletions resources/setup2-0.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<?php

use Tester\Runner\OutputHandler;
use Tester\Runner\Runner;


$userSetupScript = \getenv('INTELLIJ_NETTE_TESTER_USER_SETUP');
if ($userSetupScript) {
require_once $userSetupScript;
}


final class TeamCityOutputHandler implements OutputHandler
{

/**
* @var resource
*/
private $file;


public function __construct($output = 'php://output')
{
$this->file = \fopen($output, 'w');
}


public function begin(): void
{
// \fwrite($this->file, $this->message('testCount', array('count' => 0)));
}

function prepare(\Tester\Runner\Test $test): void
{
// TODO: Implement prepare() method.
}

function finish(\Tester\Runner\Test $test): void
{
$testName = $test->title ?: $test->getFile();
$result = $test->getResult();
$message = $test->message;

$flowId = \md5($testName);
\fwrite($this->file, $this->message('testStarted', array('name' => $testName, 'flowId' => $flowId)));

if ($result === \Tester\Runner\Test::SKIPPED) { // Runner::SKIPPED, Test::SKIPPED
\fwrite($this->file, $this->message('testIgnored', array('name' => $testName, 'flowId' => $flowId, 'message' => 'Test skipped', 'details' => $message)));

} elseif ($result === \Tester\Runner\Test::FAILED) { // Runner::FAILED, Test::FAILED
$extraArguments = array();
if (\preg_match("/^diff \"(.*)\" \"(.*)\"$/m", $message, $matches)) { // Windows build
$expectedFile = \str_replace('""', '"', $matches[1]);
$actualFile = \str_replace('""', '"', $matches[2]);
$extraArguments = array('type' => 'comparisonFailure', 'expectedFile' => $expectedFile, 'actualFile' => $actualFile);

} elseif (\preg_match("/^diff '?(.*)'? '?(.*)'?$/m", $message, $matches)) {
$expectedFile = \trim($matches[1], "'");
$actualFile = \trim($matches[2], "'");
$extraArguments = array('type' => 'comparisonFailure', 'expectedFile' => $expectedFile, 'actualFile' => $actualFile);

} elseif (\preg_match("/Failed: (.*) should be( equal to)?\s+\.*\s*(.*) in/is", $message, $matches)) {
$expected = $matches[3];
$actual = $matches[1];
$extraArguments = array('type' => 'comparisonFailure', 'expected' => $expected, 'actual' => $actual);
}

$args = \array_merge(array(
'name' => $testName,
'flowId' => $flowId,
'message' => 'Test failed',
'details' => $message,
), $extraArguments);

\fwrite($this->file, $this->message('testFailed', $args));
}

\fwrite($this->file, $this->message('testFinished', array('name' => $testName, 'flowId' => $flowId)));
}


public function end(): void
{
}


private function message($messageName, $args): string
{
$argsPairs = array();
foreach ($args as $arg => $value) {
$argsPairs[] = \sprintf("%s='%s'", $arg, $this->escape($value));
}

return \sprintf(
"##teamcity[%s %s]\n\n",
$messageName,
\implode(' ', $argsPairs)
);
}


private function escape($value): string
{
$replace = array(
"|" => "||",
"'" => "|'",
"\n" => "|n",
"\r" => "|r",
"]" => "|]",
"[" => "|[",
);

return \strtr($value, $replace);
}

}


/** @var Runner $runner */
// replace registered output handlers with TC
$runner->outputHandlers = array();
$runner->outputHandlers[] = new TeamCityOutputHandler();
14 changes: 14 additions & 0 deletions src/cz/jiripudil/intellij/nette/tester/TesterIcons.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package cz.jiripudil.intellij.nette.tester;

import com.intellij.openapi.util.IconLoader;

import javax.swing.*;

public class TesterIcons {
/** file icon */
public static final Icon RUN_CLASS = IconLoader.getIcon("/icons/runClass.png");
public static final Icon RUN_METHOD = IconLoader.getIcon("/icons/runMethod.png");
public static final Icon RUN = IconLoader.getIcon("/icons/run.png");
public static final Icon TESTER_CONFIG = IconLoader.getIcon("/icons/testConfig.png");

}
Original file line number Diff line number Diff line change
@@ -1,24 +1,15 @@
package cz.jiripudil.intellij.nette.tester;

import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupActivity;
import com.intellij.testIntegration.LanguageTestCreators;
import com.jetbrains.php.lang.PhpLanguage;
import cz.jiripudil.intellij.nette.tester.codeGeneration.TesterTestCreator;
import org.jetbrains.annotations.NotNull;

public class TesterTestCreatorEnabler implements ApplicationComponent {
public class TesterPostStartupActivity implements StartupActivity {
@Override
public void initComponent() {
public void runActivity(@NotNull Project project) {
LanguageTestCreators.INSTANCE.addExplicitExtension(PhpLanguage.INSTANCE, TesterTestCreator.INSTANCE);
}

@Override
public void disposeComponent() {
}

@NotNull
@Override
public String getComponentName() {
return this.getClass().getName();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public Collection<PsiElement> findClassesForTest(@NotNull PsiElement psiElement)
public boolean isTest(@NotNull PsiElement psiElement) {
PsiFile containingFile = psiElement.getContainingFile();
return containingFile instanceof PhpPsiElement && (
(containingFile.getVirtualFile().getExtension() != null && containingFile.getVirtualFile().getExtension().equals("phpt"))
(containingFile.getVirtualFile() != null && containingFile.getVirtualFile().getExtension() != null && containingFile.getVirtualFile().getExtension().equals("phpt"))
|| StringUtil.endsWith(containingFile.getName(), "Test")
);
}
Expand Down
Loading

0 comments on commit 8c79318

Please sign in to comment.