diff --git a/.gitignore b/.gitignore
index 374b9f4..cc9af80 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,6 @@
/vendor/
/tests/_data/node_modules/
-/tests/_data/reports/
+/tests/_data/actual/
/tests/_output/
/tests/_support/_generated/
diff --git a/.travis.yml b/.travis.yml
index 654a38c..169c5ac 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,7 +8,7 @@ php:
- '7.0'
env:
- - COMPOSER_NO_INTERACTION=1 COMPOSER_DISABLE_XDEBUG_WARN=1
+ - 'COMPOSER_NO_INTERACTION=1 COMPOSER_DISABLE_XDEBUG_WARN=1'
cache:
directories:
diff --git a/RoboFile.php b/RoboFile.php
index 89ce63b..a219191 100644
--- a/RoboFile.php
+++ b/RoboFile.php
@@ -2,6 +2,7 @@
// @codingStandardsIgnoreStart
use Symfony\Component\Process\Process;
+use Symfony\Component\Yaml\Yaml;
/**
* Class RoboFile.
@@ -16,6 +17,11 @@ class RoboFile extends \Robo\Tasks
*/
protected $composerInfo = [];
+ /**
+ * @var array
+ */
+ protected $codeceptionInfo = [];
+
/**
* @var string
*/
@@ -71,7 +77,12 @@ public function githookPreCommit()
*/
public function test()
{
- return $this->getTaskCodecept();
+ /** @var \Robo\Collection\CollectionBuilder $cb */
+ $cb = $this->collectionBuilder();
+
+ return $cb->addTaskList([
+ 'codecept' => $this->getTaskCodecept(),
+ ]);
}
/**
@@ -83,11 +94,12 @@ public function lint()
{
/** @var \Robo\Collection\CollectionBuilder $cb */
$cb = $this->collectionBuilder();
-
- return $cb->addTaskList([
+ $cb->addTaskList([
'lint.composer.lock' => $this->taskComposerValidate(),
'lint.phpcs.psr2' => $this->getTaskPhpcsLint(),
]);
+
+ return $cb;
}
/**
@@ -109,6 +121,28 @@ protected function initComposerInfo()
return $this;
}
+ /**
+ * @return $this
+ */
+ protected function initCodeceptionInfo()
+ {
+ if ($this->codeceptionInfo) {
+ return $this;
+ }
+
+ if (is_readable('codeception.yml')) {
+ $this->codeceptionInfo = Yaml::parse(file_get_contents('codeception.yml'));
+ } else {
+ $this->codeceptionInfo = [
+ 'paths' => [
+ 'log' => 'tests/_output',
+ ],
+ ];
+ }
+
+ return $this;
+ }
+
/**
* @return \Cheppers\Robo\Phpcs\Task\TaskPhpcsLint
*/
@@ -119,7 +153,6 @@ protected function getTaskPhpcsLint()
'standard' => 'PSR2',
'reports' => [
'full' => null,
- 'checkstyle' => 'tests/_output/checkstyle/phpcs-psr2.xml',
],
'files' => [
'src/',
@@ -133,10 +166,12 @@ protected function getTaskPhpcsLint()
}
/**
- * @return \Robo\Task\Base\Exec
+ * @return \Robo\Collection\CollectionBuilder
*/
protected function getTaskCodecept()
{
+ $this->initCodeceptionInfo();
+
$cmd_args = [];
if ($this->isPhpExtensionAvailable('xdebug')) {
$cmd_pattern = '%s';
@@ -147,13 +182,30 @@ protected function getTaskCodecept()
$cmd_args[] = escapeshellarg("{$this->binDir}/codecept");
}
- $cmd_pattern .= ' --ansi --verbose --coverage --coverage-xml=%s --coverage-html=%s run';
- $cmd_args[] = escapeshellarg('coverage.xml');
- $cmd_args[] = escapeshellarg('html');
+ $cmd_pattern .= ' --ansi';
+ $cmd_pattern .= ' --verbose';
+
+ $cmd_pattern .= ' --coverage=%s';
+ $cmd_args[] = escapeshellarg('coverage/coverage.serialized');
+
+ $cmd_pattern .= ' --coverage-xml=%s';
+ $cmd_args[] = escapeshellarg('coverage/coverage.xml');
+
+ $cmd_pattern .= ' --coverage-html=%s';
+ $cmd_args[] = escapeshellarg('coverage/html');
+
+ $cmd_pattern .= ' run';
+
+ $reportsDir = $this->codeceptionInfo['paths']['log'];
+
+ /** @var \Robo\Collection\CollectionBuilder $cb */
+ $cb = $this->collectionBuilder();
+ $cb->addTaskList([
+ 'prepareCoverageDir' => $this->taskFilesystemStack()->mkdir("$reportsDir/coverage"),
+ 'runCodeception' => $this->taskExec(vsprintf($cmd_pattern, $cmd_args)),
+ ]);
- return $this
- ->taskExec(vsprintf($cmd_pattern, $cmd_args))
- ->printed(false);
+ return $cb;
}
/**
diff --git a/composer.json b/composer.json
index 8c7107a..7570426 100644
--- a/composer.json
+++ b/composer.json
@@ -10,13 +10,16 @@
"prefer-stable": true,
"require": {
"cheppers/asset-jar": "^0.0",
- "consolidation/robo": "1.0.0-RC2"
+ "consolidation/robo": "1.0.0-RC2",
+ "samsonasik/package-versions": "^1.1"
},
"require-dev": {
"cheppers/git-hooks": "^0.0.8",
- "cheppers/robo-phpcs": "^0.0.4",
+ "cheppers/lint-report": "^0.0.4",
+ "cheppers/robo-phpcs": "^0.0.7",
"codeception/codeception": "^2.2",
- "symfony/process": "^2.8|^3.1"
+ "symfony/process": "^2.8 || ^3.1",
+ "symfony/yaml": "^2.8 || ^3.1"
},
"autoload": {
"psr-4": {
diff --git a/composer.lock b/composer.lock
index b38df3e..eb7ebcc 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "hash": "f3bede9cae0b2f6eb8930ff55257d091",
- "content-hash": "9918e697a3bbc75a52d4702f8a3a6e41",
+ "hash": "a6f3bafeed32e4451fce48f3fbc77d20",
+ "content-hash": "e7ac6f86384143adbcf383ae5393721f",
"packages": [
{
"name": "cheppers/asset-jar",
@@ -41,16 +41,16 @@
},
{
"name": "consolidation/annotated-command",
- "version": "1.2.2",
+ "version": "1.4.1",
"source": {
"type": "git",
- "url": "https://github.com/consolidation-org/annotated-command.git",
- "reference": "6d6bacf27893d265d6b71e7c2fa2da661ce891c4"
+ "url": "https://github.com/consolidation/annotated-command.git",
+ "reference": "c2dc2464e1edf0498bf97a99f34cac5805d00946"
},
"dist": {
"type": "zip",
- "url": "https://github.com/gitapi/repos/consolidation-org/annotated-command/zipball/6d6bacf27893d265d6b71e7c2fa2da661ce891c4",
- "reference": "6d6bacf27893d265d6b71e7c2fa2da661ce891c4",
+ "url": "https://github.com/gitapi/repos/consolidation/annotated-command/zipball/c2dc2464e1edf0498bf97a99f34cac5805d00946",
+ "reference": "c2dc2464e1edf0498bf97a99f34cac5805d00946",
"shasum": ""
},
"require": {
@@ -89,19 +89,19 @@
}
],
"description": "Initialize Symfony Console commands from annotated command class methods.",
- "time": "2016-08-19 22:56:42"
+ "time": "2016-09-13 21:37:50"
},
{
"name": "consolidation/log",
"version": "1.0.3",
"source": {
"type": "git",
- "url": "https://github.com/consolidation-org/log.git",
+ "url": "https://github.com/consolidation/log.git",
"reference": "74ba81b4edc585616747cc5c5309ce56fec41254"
},
"dist": {
"type": "zip",
- "url": "https://github.com/gitapi/repos/consolidation-org/log/zipball/74ba81b4edc585616747cc5c5309ce56fec41254",
+ "url": "https://github.com/gitapi/repos/consolidation/log/zipball/74ba81b4edc585616747cc5c5309ce56fec41254",
"reference": "74ba81b4edc585616747cc5c5309ce56fec41254",
"shasum": ""
},
@@ -140,16 +140,16 @@
},
{
"name": "consolidation/output-formatters",
- "version": "1.0.0",
+ "version": "1.1.0",
"source": {
"type": "git",
- "url": "https://github.com/consolidation-org/output-formatters.git",
- "reference": "6428d8fb30c9ed3b96314580808b3e4415b46dd9"
+ "url": "https://github.com/consolidation/output-formatters.git",
+ "reference": "aadb1ed2deb72bc1351bb6f3b3ddd328222e9261"
},
"dist": {
"type": "zip",
- "url": "https://github.com/gitapi/repos/consolidation-org/output-formatters/zipball/6428d8fb30c9ed3b96314580808b3e4415b46dd9",
- "reference": "6428d8fb30c9ed3b96314580808b3e4415b46dd9",
+ "url": "https://github.com/gitapi/repos/consolidation/output-formatters/zipball/aadb1ed2deb72bc1351bb6f3b3ddd328222e9261",
+ "reference": "aadb1ed2deb72bc1351bb6f3b3ddd328222e9261",
"shasum": ""
},
"require": {
@@ -183,19 +183,19 @@
}
],
"description": "Format text by applying transformations provided by plug-in formatters.",
- "time": "2016-05-20 04:17:55"
+ "time": "2016-09-14 23:51:08"
},
{
"name": "consolidation/robo",
"version": "1.0.0-RC2",
"source": {
"type": "git",
- "url": "https://github.com/consolidation-org/Robo.git",
+ "url": "https://github.com/consolidation/Robo.git",
"reference": "abdae8e8e6d0872df9b02031c6d2f1b7364f3113"
},
"dist": {
"type": "zip",
- "url": "https://github.com/gitapi/repos/consolidation-org/Robo/zipball/abdae8e8e6d0872df9b02031c6d2f1b7364f3113",
+ "url": "https://github.com/gitapi/repos/consolidation/Robo/zipball/abdae8e8e6d0872df9b02031c6d2f1b7364f3113",
"reference": "abdae8e8e6d0872df9b02031c6d2f1b7364f3113",
"shasum": ""
},
@@ -406,16 +406,16 @@
},
{
"name": "phpdocumentor/reflection-docblock",
- "version": "3.1.0",
+ "version": "3.1.1",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
- "reference": "9270140b940ff02e58ec577c237274e92cd40cdd"
+ "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e"
},
"dist": {
"type": "zip",
- "url": "https://github.com/gitapi/repos/phpDocumentor/ReflectionDocBlock/zipball/9270140b940ff02e58ec577c237274e92cd40cdd",
- "reference": "9270140b940ff02e58ec577c237274e92cd40cdd",
+ "url": "https://github.com/gitapi/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e",
+ "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e",
"shasum": ""
},
"require": {
@@ -447,7 +447,7 @@
}
],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
- "time": "2016-06-10 09:48:41"
+ "time": "2016-09-30 07:12:33"
},
{
"name": "phpdocumentor/type-resolver",
@@ -498,22 +498,30 @@
},
{
"name": "psr/log",
- "version": "1.0.0",
+ "version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
- "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b"
+ "reference": "5277094ed527a1c4477177d102fe4c53551953e0"
},
"dist": {
"type": "zip",
- "url": "https://github.com/gitapi/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b",
- "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b",
+ "url": "https://github.com/gitapi/repos/php-fig/log/zipball/5277094ed527a1c4477177d102fe4c53551953e0",
+ "reference": "5277094ed527a1c4477177d102fe4c53551953e0",
"shasum": ""
},
+ "require": {
+ "php": ">=5.3.0"
+ },
"type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
"autoload": {
- "psr-0": {
- "Psr\\Log\\": ""
+ "psr-4": {
+ "Psr\\Log\\": "Psr/Log/"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -527,35 +535,86 @@
}
],
"description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
"keywords": [
"log",
"psr",
"psr-3"
],
- "time": "2012-12-21 11:40:51"
+ "time": "2016-09-19 16:02:08"
+ },
+ {
+ "name": "samsonasik/package-versions",
+ "version": "1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/samsonasik/PackageVersions.git",
+ "reference": "1dab884977464613383afe0e4be571cdef2317fc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://github.com/gitapi/repos/samsonasik/PackageVersions/zipball/1dab884977464613383afe0e4be571cdef2317fc",
+ "reference": "1dab884977464613383afe0e4be571cdef2317fc",
+ "shasum": ""
+ },
+ "require": {
+ "composer-plugin-api": "^1.0",
+ "php": "^5.6 || ^7.0"
+ },
+ "replace": {
+ "ocramius/package-versions": ">=1.0.0"
+ },
+ "require-dev": {
+ "composer/composer": "^1.0.0-ALPHA11@ALPHA",
+ "phpunit/phpunit": "^5.2.8"
+ },
+ "type": "composer-plugin",
+ "extra": {
+ "class": "PackageVersions\\Installer",
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "PackageVersions\\": "src/PackageVersions"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Marco Pivetta",
+ "email": "ocramius@gmail.com"
+ }
+ ],
+ "description": "A backport of ocramius/package-versions that supports php ^5.6. Composer plugin that provides efficient querying for installed package versions (no runtime IO)",
+ "time": "2016-07-21 12:03:58"
},
{
"name": "symfony/console",
- "version": "v3.1.4",
+ "version": "v2.8.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "8ea494c34f0f772c3954b5fbe00bffc5a435e563"
+ "reference": "3d3e4fa5f0614c8e45220e5de80332322e33bd90"
},
"dist": {
"type": "zip",
- "url": "https://github.com/gitapi/repos/symfony/console/zipball/8ea494c34f0f772c3954b5fbe00bffc5a435e563",
- "reference": "8ea494c34f0f772c3954b5fbe00bffc5a435e563",
+ "url": "https://github.com/gitapi/repos/symfony/console/zipball/3d3e4fa5f0614c8e45220e5de80332322e33bd90",
+ "reference": "3d3e4fa5f0614c8e45220e5de80332322e33bd90",
"shasum": ""
},
"require": {
- "php": ">=5.5.9",
+ "php": ">=5.3.9",
"symfony/polyfill-mbstring": "~1.0"
},
"require-dev": {
"psr/log": "~1.0",
- "symfony/event-dispatcher": "~2.8|~3.0",
- "symfony/process": "~2.8|~3.0"
+ "symfony/event-dispatcher": "~2.1|~3.0.0",
+ "symfony/process": "~2.1|~3.0.0"
},
"suggest": {
"psr/log": "For using the console logger",
@@ -565,7 +624,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.1-dev"
+ "dev-master": "2.8-dev"
}
},
"autoload": {
@@ -592,7 +651,7 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
- "time": "2016-08-19 06:48:39"
+ "time": "2016-09-06 10:55:00"
},
{
"name": "symfony/event-dispatcher",
@@ -656,25 +715,25 @@
},
{
"name": "symfony/filesystem",
- "version": "v3.1.4",
+ "version": "v2.8.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "bb29adceb552d202b6416ede373529338136e84f"
+ "reference": "44b499521defddf2eae17a18c811bbdae4f98bdf"
},
"dist": {
"type": "zip",
- "url": "https://github.com/gitapi/repos/symfony/filesystem/zipball/bb29adceb552d202b6416ede373529338136e84f",
- "reference": "bb29adceb552d202b6416ede373529338136e84f",
+ "url": "https://github.com/gitapi/repos/symfony/filesystem/zipball/44b499521defddf2eae17a18c811bbdae4f98bdf",
+ "reference": "44b499521defddf2eae17a18c811bbdae4f98bdf",
"shasum": ""
},
"require": {
- "php": ">=5.5.9"
+ "php": ">=5.3.9"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.1-dev"
+ "dev-master": "2.8-dev"
}
},
"autoload": {
@@ -701,7 +760,7 @@
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
- "time": "2016-07-20 05:44:26"
+ "time": "2016-09-06 10:55:00"
},
{
"name": "symfony/finder",
@@ -914,16 +973,16 @@
"packages-dev": [
{
"name": "behat/gherkin",
- "version": "v4.4.2",
+ "version": "v4.4.4",
"source": {
"type": "git",
"url": "https://github.com/Behat/Gherkin.git",
- "reference": "d26757dc970e67b50ed0ee47b95273daeb84fea6"
+ "reference": "cf8cc94647101e02a33d690245896d83d880aea1"
},
"dist": {
"type": "zip",
- "url": "https://github.com/gitapi/repos/Behat/Gherkin/zipball/d26757dc970e67b50ed0ee47b95273daeb84fea6",
- "reference": "d26757dc970e67b50ed0ee47b95273daeb84fea6",
+ "url": "https://github.com/gitapi/repos/Behat/Gherkin/zipball/cf8cc94647101e02a33d690245896d83d880aea1",
+ "reference": "cf8cc94647101e02a33d690245896d83d880aea1",
"shasum": ""
},
"require": {
@@ -969,7 +1028,7 @@
"gherkin",
"parser"
],
- "time": "2016-09-03 07:28:57"
+ "time": "2016-09-18 12:16:14"
},
{
"name": "cheppers/git-hooks",
@@ -1013,26 +1072,67 @@
"time": "2016-07-10 07:41:08"
},
{
- "name": "cheppers/robo-phpcs",
+ "name": "cheppers/lint-report",
"version": "v0.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Cheppers/lint-report.git",
+ "reference": "5bbd4429f06b50c893ee30f74ce4ba02ea5a64aa"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://github.com/gitapi/repos/Cheppers/lint-report/zipball/5bbd4429f06b50c893ee30f74ce4ba02ea5a64aa",
+ "reference": "5bbd4429f06b50c893ee30f74ce4ba02ea5a64aa",
+ "shasum": ""
+ },
+ "require": {
+ "league/container": "^2.2",
+ "symfony/console": "^2.8",
+ "symfony/filesystem": "^2.8",
+ "symfony/yaml": "^2.8 || ^3.1"
+ },
+ "require-dev": {
+ "cheppers/git-hooks": "^0.0.8",
+ "codeception/codeception": "^2.2",
+ "squizlabs/php_codesniffer": "2.6.2"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Cheppers\\LintReport\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "GPL-2.0+"
+ ],
+ "description": "Generate reports from lint results",
+ "time": "2016-10-02 12:00:15"
+ },
+ {
+ "name": "cheppers/robo-phpcs",
+ "version": "v0.0.7",
"source": {
"type": "git",
"url": "https://github.com/Cheppers/robo-phpcs.git",
- "reference": "5b6ee2c22eb41247968cb82d05cb44fa73bcc901"
+ "reference": "04737eb2d3dadcbc7c4d0e9d91bdee8e1b69307b"
},
"dist": {
"type": "zip",
- "url": "https://github.com/gitapi/repos/Cheppers/robo-phpcs/zipball/5b6ee2c22eb41247968cb82d05cb44fa73bcc901",
- "reference": "5b6ee2c22eb41247968cb82d05cb44fa73bcc901",
+ "url": "https://github.com/gitapi/repos/Cheppers/robo-phpcs/zipball/04737eb2d3dadcbc7c4d0e9d91bdee8e1b69307b",
+ "reference": "04737eb2d3dadcbc7c4d0e9d91bdee8e1b69307b",
"shasum": ""
},
"require": {
+ "cheppers/asset-jar": "^0.0.1",
+ "cheppers/lint-report": "^0.0.4",
"consolidation/robo": "1.0.0-RC2",
"squizlabs/php_codesniffer": "^2.6"
},
"require-dev": {
"cheppers/git-hooks": "^0.0.8",
- "codeception/codeception": "^2.2"
+ "codeception/codeception": "^2.2",
+ "symfony/yaml": "^2.8 || ^3.1"
},
"type": "library",
"autoload": {
@@ -1045,20 +1145,20 @@
"GPL-2.0+"
],
"description": "Robo task wrapper for PHPCS",
- "time": "2016-09-03 21:22:10"
+ "time": "2016-10-02 12:13:44"
},
{
"name": "codeception/codeception",
- "version": "2.2.4",
+ "version": "2.2.5",
"source": {
"type": "git",
"url": "https://github.com/Codeception/Codeception.git",
- "reference": "ea617b8b55e6e33cdd47edeafde5d3f6466049e2"
+ "reference": "b4729341e469d0f174f3cade85718ff5bf8dd751"
},
"dist": {
"type": "zip",
- "url": "https://github.com/gitapi/repos/Codeception/Codeception/zipball/ea617b8b55e6e33cdd47edeafde5d3f6466049e2",
- "reference": "ea617b8b55e6e33cdd47edeafde5d3f6466049e2",
+ "url": "https://github.com/gitapi/repos/Codeception/Codeception/zipball/b4729341e469d0f174f3cade85718ff5bf8dd751",
+ "reference": "b4729341e469d0f174f3cade85718ff5bf8dd751",
"shasum": ""
},
"require": {
@@ -1069,8 +1169,8 @@
"guzzlehttp/guzzle": ">=4.1.4 <7.0",
"guzzlehttp/psr7": "~1.0",
"php": ">=5.4.0 <8.0",
- "phpunit/php-code-coverage": ">=2.1.3",
- "phpunit/phpunit": ">4.8.20 <5.5",
+ "phpunit/php-code-coverage": ">=2.1.3 <5.0",
+ "phpunit/phpunit": ">4.8.20 <6.0",
"sebastian/comparator": "~1.1",
"sebastian/diff": "^1.4",
"symfony/browser-kit": ">=2.7 <4.0",
@@ -1083,7 +1183,7 @@
},
"require-dev": {
"codeception/specify": "~0.3",
- "facebook/php-sdk-v4": "~5.0",
+ "facebook/graph-sdk": "~5.3",
"flow/jsonpath": "~0.2",
"league/factory-muffin": "^3.0",
"league/factory-muffin-faker": "^1.0",
@@ -1136,7 +1236,7 @@
"functional testing",
"unit testing"
],
- "time": "2016-08-14 12:28:58"
+ "time": "2016-09-29 01:29:59"
},
{
"name": "doctrine/instantiator",
@@ -1411,16 +1511,16 @@
},
{
"name": "myclabs/deep-copy",
- "version": "1.5.1",
+ "version": "1.5.4",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
- "reference": "a8773992b362b58498eed24bf85005f363c34771"
+ "reference": "ea74994a3dc7f8d2f65a06009348f2d63c81e61f"
},
"dist": {
"type": "zip",
- "url": "https://github.com/gitapi/repos/myclabs/DeepCopy/zipball/a8773992b362b58498eed24bf85005f363c34771",
- "reference": "a8773992b362b58498eed24bf85005f363c34771",
+ "url": "https://github.com/gitapi/repos/myclabs/DeepCopy/zipball/ea74994a3dc7f8d2f65a06009348f2d63c81e61f",
+ "reference": "ea74994a3dc7f8d2f65a06009348f2d63c81e61f",
"shasum": ""
},
"require": {
@@ -1449,7 +1549,7 @@
"object",
"object graph"
],
- "time": "2015-11-20 12:04:31"
+ "time": "2016-09-16 13:37:59"
},
{
"name": "phpspec/prophecy",
@@ -1759,24 +1859,24 @@
},
{
"name": "phpunit/phpunit",
- "version": "5.4.8",
+ "version": "5.5.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "3132365e1430c091f208e120b8845d39c25f20e6"
+ "reference": "a57126dc681b08289fef6ac96a48e30656f84350"
},
"dist": {
"type": "zip",
- "url": "https://github.com/gitapi/repos/sebastianbergmann/phpunit/zipball/3132365e1430c091f208e120b8845d39c25f20e6",
- "reference": "3132365e1430c091f208e120b8845d39c25f20e6",
+ "url": "https://github.com/gitapi/repos/sebastianbergmann/phpunit/zipball/a57126dc681b08289fef6ac96a48e30656f84350",
+ "reference": "a57126dc681b08289fef6ac96a48e30656f84350",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-json": "*",
- "ext-pcre": "*",
- "ext-reflection": "*",
- "ext-spl": "*",
+ "ext-libxml": "*",
+ "ext-mbstring": "*",
+ "ext-xml": "*",
"myclabs/deep-copy": "~1.3",
"php": "^5.6 || ^7.0",
"phpspec/prophecy": "^1.3.1",
@@ -1798,7 +1898,12 @@
"conflict": {
"phpdocumentor/reflection-docblock": "3.0.2"
},
+ "require-dev": {
+ "ext-pdo": "*"
+ },
"suggest": {
+ "ext-tidy": "*",
+ "ext-xdebug": "*",
"phpunit/php-invoker": "~1.1"
},
"bin": [
@@ -1807,7 +1912,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.4.x-dev"
+ "dev-master": "5.5.x-dev"
}
},
"autoload": {
@@ -1833,20 +1938,20 @@
"testing",
"xunit"
],
- "time": "2016-07-26 14:48:00"
+ "time": "2016-09-21 14:40:13"
},
{
"name": "phpunit/phpunit-mock-objects",
- "version": "3.2.6",
+ "version": "3.2.7",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
- "reference": "46b249b43fd2ed8e127aa0fdb3cbcf56e9bc0e49"
+ "reference": "546898a2c0c356ef2891b39dd7d07f5d82c8ed0a"
},
"dist": {
"type": "zip",
- "url": "https://github.com/gitapi/repos/sebastianbergmann/phpunit-mock-objects/zipball/46b249b43fd2ed8e127aa0fdb3cbcf56e9bc0e49",
- "reference": "46b249b43fd2ed8e127aa0fdb3cbcf56e9bc0e49",
+ "url": "https://github.com/gitapi/repos/sebastianbergmann/phpunit-mock-objects/zipball/546898a2c0c356ef2891b39dd7d07f5d82c8ed0a",
+ "reference": "546898a2c0c356ef2891b39dd7d07f5d82c8ed0a",
"shasum": ""
},
"require": {
@@ -1892,7 +1997,7 @@
"mock",
"xunit"
],
- "time": "2016-08-26 05:51:59"
+ "time": "2016-09-06 16:07:45"
},
{
"name": "psr/http-message",
diff --git a/src/LintReportWrapper/Json/FailureWrapper.php b/src/LintReportWrapper/Json/FailureWrapper.php
new file mode 100644
index 0000000..068fc91
--- /dev/null
+++ b/src/LintReportWrapper/Json/FailureWrapper.php
@@ -0,0 +1,73 @@
+failure = $failure + [
+ 'severity' => '',
+ 'source' => '',
+ 'message' => '',
+ 'line' => 0,
+ 'column' => 0,
+ ];
+ }
+
+ /**
+ * @return string
+ */
+ public function severity()
+ {
+ return $this->failure['severity'];
+ }
+
+ /**
+ * @return string
+ */
+ public function source()
+ {
+ return $this->failure['source'];
+ }
+
+ /**
+ * @return int
+ */
+ public function line()
+ {
+ return $this->failure['line'];
+ }
+
+ /**
+ * @return int
+ */
+ public function column()
+ {
+ return $this->failure['column'];
+ }
+
+ /**
+ * @return string
+ */
+ public function message()
+ {
+ return $this->failure['message'];
+ }
+}
diff --git a/src/LintReportWrapper/Json/FileWrapper.php b/src/LintReportWrapper/Json/FileWrapper.php
new file mode 100644
index 0000000..55c0d84
--- /dev/null
+++ b/src/LintReportWrapper/Json/FileWrapper.php
@@ -0,0 +1,151 @@
+file = $file + [
+ 'filePath' => '',
+ 'errors' => 0,
+ 'warnings' => 0,
+ 'stats' => [],
+ 'failures' => [],
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function filePath()
+ {
+ return $this->file['filePath'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function numOfErrors()
+ {
+ return $this->file['errors'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function numOfWarnings()
+ {
+ return $this->file['warnings'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function yieldFailures()
+ {
+ foreach ($this->file['failures'] as $failure) {
+ yield new FailureWrapper($failure);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function stats()
+ {
+ if (!$this->file['stats']) {
+ $this->file['stats'] = [
+ 'severity' => 'ok',
+ 'has' => [
+ ReportWrapperInterface::SEVERITY_OK => false,
+ ReportWrapperInterface::SEVERITY_WARNING => false,
+ ReportWrapperInterface::SEVERITY_ERROR => false,
+ ],
+ 'source' => [],
+ ];
+ foreach ($this->file['failures'] as $failure) {
+ if ($this->severityComparer($this->file['stats']['severity'], $failure['severity']) === 1) {
+ $this->file['stats']['severity'] = $failure['severity'];
+ }
+
+ $this->file['stats']['has'][$failure['severity']] = true;
+
+ $this->file['stats']['source'] += [
+ $failure['source'] => [
+ 'severity' => $failure['severity'],
+ 'count' => 0,
+ ],
+ ];
+ $this->file['stats']['source'][$failure['source']]['count']++;
+ }
+ }
+
+ return $this->file['stats'];
+ }
+
+
+ /**
+ * @return string
+ */
+ public function highestSeverity()
+ {
+ if ($this->numOfErrors()) {
+ return ReportWrapperInterface::SEVERITY_ERROR;
+ }
+
+ if ($this->numOfWarnings()) {
+ return ReportWrapperInterface::SEVERITY_WARNING;
+ }
+
+ return ReportWrapperInterface::SEVERITY_OK;
+ }
+
+ /**
+ * @param string $a
+ * @param string $b
+ *
+ * @return int
+ */
+ protected function severityComparer($a, $b)
+ {
+ $weights = [
+ 'ok',
+ 'warning',
+ 'error',
+ ];
+
+ if ($a === $b) {
+ return 0;
+ }
+
+ $aWeight = array_search($a, $weights);
+ $bWeight = array_search($b, $weights);
+
+ if ($aWeight === false) {
+ return -1;
+ }
+
+ if ($bWeight === false) {
+ return 1;
+ }
+
+ return $aWeight > $bWeight ? -1 : 1;
+ }
+}
diff --git a/src/LintReportWrapper/Json/ReportWrapper.php b/src/LintReportWrapper/Json/ReportWrapper.php
new file mode 100644
index 0000000..2a028be
--- /dev/null
+++ b/src/LintReportWrapper/Json/ReportWrapper.php
@@ -0,0 +1,136 @@
+setReport($report);
+ }
+ }
+
+ /**
+ * @return array
+ */
+ public function getReport()
+ {
+ return $this->report;
+ }
+
+ /**
+ * @param array $report
+ *
+ * @return $this
+ */
+ public function setReport($report)
+ {
+ $this->report = $report;
+ $this->reportInternal = [];
+ $this->numOfErrors = 0;
+ $this->numOfWarnings = 0;
+
+ foreach ($report as $filePath => $failures) {
+ $this->reportInternal[$filePath] = [
+ 'filePath' => $filePath,
+ 'errors' => 0,
+ 'warnings' => 0,
+ 'stats' => [],
+ 'failures' => $failures,
+ ];
+
+ foreach ($failures as $failure) {
+ if ($failure['severity'] === 'error') {
+ $this->reportInternal[$filePath]['errors']++;
+ $this->numOfErrors++;
+ } elseif ($failure['severity'] === 'warning') {
+ $this->reportInternal[$filePath]['warnings']++;
+ $this->numOfWarnings++;
+ }
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function countFiles()
+ {
+ return count($this->reportInternal);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function yieldFiles()
+ {
+ foreach ($this->reportInternal as $filePath => $file) {
+ yield $filePath => new FileWrapper($file);
+ }
+ }
+
+ /**
+ * @return string
+ */
+ public function highestSeverity()
+ {
+ if ($this->numOfErrors()) {
+ return ReportWrapperInterface::SEVERITY_ERROR;
+ }
+
+ if ($this->numOfWarnings()) {
+ return ReportWrapperInterface::SEVERITY_WARNING;
+ }
+
+ return ReportWrapperInterface::SEVERITY_OK;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function numOfErrors()
+ {
+ return $this->numOfErrors;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function numOfWarnings()
+ {
+ return $this->numOfWarnings;
+ }
+}
diff --git a/src/LintReportWrapper/Yaml/FailureWrapper.php b/src/LintReportWrapper/Yaml/FailureWrapper.php
new file mode 100644
index 0000000..4c17163
--- /dev/null
+++ b/src/LintReportWrapper/Yaml/FailureWrapper.php
@@ -0,0 +1,82 @@
+failure = $failure + [
+ 'failure' => '',
+ 'severity' => 'error',
+ 'name' => '',
+ 'ruleName' => '',
+ 'startPosition' => [
+ 'line' => 0,
+ 'character' => 0,
+ 'position' => 0,
+ ],
+ 'endPosition' => [
+ 'line' => 0,
+ 'character' => 0,
+ 'position' => 0,
+ ],
+ ];
+ }
+
+ /**
+ * @return string
+ */
+ public function severity()
+ {
+ return $this->failure['severity'];
+ }
+
+ /**
+ * @return string
+ */
+ public function source()
+ {
+ return $this->failure['ruleName'];
+ }
+
+ /**
+ * @return int
+ */
+ public function line()
+ {
+ return $this->failure['startPosition']['line'];
+ }
+
+ /**
+ * @return int
+ */
+ public function column()
+ {
+ return $this->failure['startPosition']['character'];
+ }
+
+ /**
+ * @return string
+ */
+ public function message()
+ {
+ return $this->failure['failure'];
+ }
+}
diff --git a/src/LintReportWrapper/Yaml/FileWrapper.php b/src/LintReportWrapper/Yaml/FileWrapper.php
new file mode 100644
index 0000000..96c5412
--- /dev/null
+++ b/src/LintReportWrapper/Yaml/FileWrapper.php
@@ -0,0 +1,151 @@
+file = $file + [
+ 'filePath' => '',
+ 'errors' => 0,
+ 'warnings' => 0,
+ 'stats' => [],
+ 'failures' => [],
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function filePath()
+ {
+ return $this->file['filePath'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function numOfErrors()
+ {
+ return $this->file['errors'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function numOfWarnings()
+ {
+ return $this->file['warnings'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function yieldFailures()
+ {
+ foreach ($this->file['failures'] as $failure) {
+ yield new FailureWrapper($failure);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function stats()
+ {
+ if (!$this->file['stats']) {
+ $this->file['stats'] = [
+ 'severity' => 'ok',
+ 'has' => [
+ ReportWrapperInterface::SEVERITY_OK => false,
+ ReportWrapperInterface::SEVERITY_WARNING => false,
+ ReportWrapperInterface::SEVERITY_ERROR => false,
+ ],
+ 'source' => [],
+ ];
+ foreach ($this->file['failures'] as $failure) {
+ if ($this->severityComparer($this->file['stats']['severity'], $failure['severity']) === 1) {
+ $this->file['stats']['severity'] = $failure['severity'];
+ }
+
+ $this->file['stats']['has'][$failure['severity']] = true;
+
+ $this->file['stats']['source'] += [
+ $failure['ruleName'] => [
+ 'severity' => $failure['severity'],
+ 'count' => 0,
+ ],
+ ];
+ $this->file['stats']['source'][$failure['ruleName']]['count']++;
+ }
+ }
+
+ return $this->file['stats'];
+ }
+
+
+ /**
+ * @return string
+ */
+ public function highestSeverity()
+ {
+ if ($this->numOfErrors()) {
+ return ReportWrapperInterface::SEVERITY_ERROR;
+ }
+
+ if ($this->numOfWarnings()) {
+ return ReportWrapperInterface::SEVERITY_WARNING;
+ }
+
+ return ReportWrapperInterface::SEVERITY_OK;
+ }
+
+ /**
+ * @param string $a
+ * @param string $b
+ *
+ * @return int
+ */
+ protected function severityComparer($a, $b)
+ {
+ $weights = [
+ 'ok',
+ 'warning',
+ 'error',
+ ];
+
+ if ($a === $b) {
+ return 0;
+ }
+
+ $aWeight = array_search($a, $weights);
+ $bWeight = array_search($b, $weights);
+
+ if ($aWeight === false) {
+ return -1;
+ }
+
+ if ($bWeight === false) {
+ return 1;
+ }
+
+ return $aWeight > $bWeight ? -1 : 1;
+ }
+}
diff --git a/src/LintReportWrapper/Yaml/ReportWrapper.php b/src/LintReportWrapper/Yaml/ReportWrapper.php
new file mode 100644
index 0000000..ec7cfb4
--- /dev/null
+++ b/src/LintReportWrapper/Yaml/ReportWrapper.php
@@ -0,0 +1,140 @@
+setReport($report);
+ }
+ }
+
+ /**
+ * @return array
+ */
+ public function getReport()
+ {
+ return $this->report;
+ }
+
+ /**
+ * @param array $report
+ *
+ * @return $this
+ */
+ public function setReport($report)
+ {
+ $this->report = $report;
+ $this->numOfErrors = null;
+ $this->numOfWarnings = null;
+
+ foreach ($report as $document) {
+ foreach ($document['failures'] as $failure) {
+ $failure += ['severity' => 'error'];
+ $filePath = $failure['name'];
+ if (!isset($this->reportInternal[$filePath])) {
+ $this->reportInternal[$filePath] = [
+ 'filePath' => $filePath,
+ 'errors' => 0,
+ 'warnings' => 0,
+ 'stats' => [],
+ 'failures' => [],
+ ];
+ }
+
+ $this->reportInternal[$filePath]['failures'][] = $failure;
+ if ($failure['severity'] === 'error') {
+ $this->reportInternal[$filePath]['errors']++;
+ $this->numOfErrors++;
+ } elseif ($failure['severity'] === 'warning') {
+ $this->reportInternal[$filePath]['warnings']++;
+ $this->numOfWarnings++;
+ }
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function countFiles()
+ {
+ return count($this->reportInternal);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function yieldFiles()
+ {
+ foreach ($this->reportInternal as $file) {
+ yield $file['filePath'] => new FileWrapper($file);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function numOfErrors()
+ {
+ return $this->numOfErrors;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function numOfWarnings()
+ {
+ return $this->numOfWarnings;
+ }
+
+ /**
+ * @return string
+ */
+ public function highestSeverity()
+ {
+ if ($this->numOfErrors()) {
+ return ReportWrapperInterface::SEVERITY_ERROR;
+ }
+
+ if ($this->numOfWarnings()) {
+ return ReportWrapperInterface::SEVERITY_WARNING;
+ }
+
+ return ReportWrapperInterface::SEVERITY_OK;
+ }
+}
diff --git a/src/Task/LoadTasks.php b/src/Task/LoadTasks.php
index d36cdce..288e8d1 100644
--- a/src/Task/LoadTasks.php
+++ b/src/Task/LoadTasks.php
@@ -2,6 +2,9 @@
namespace Cheppers\Robo\TsLint\Task;
+use League\Container\ContainerAwareInterface;
+use Robo\Contract\OutputAwareInterface;
+
/**
* Class LoadTasks.
*
@@ -22,6 +25,16 @@ trait LoadTasks
*/
protected function taskTsLintRun(array $options = [], array $paths = [])
{
- return $this->task(Run::class, $options, $paths);
+ /** @var \Cheppers\Robo\TSLint\Task\Run $task */
+ $task = $this->task(Run::class, $options, $paths);
+ if ($this instanceof ContainerAwareInterface) {
+ $task->setContainer($this->getContainer());
+ }
+
+ if ($this instanceof OutputAwareInterface) {
+ $task->setOutput($this->output());
+ }
+
+ return $task;
}
}
diff --git a/src/Task/Run.php b/src/Task/Run.php
index e04b76d..c07049e 100644
--- a/src/Task/Run.php
+++ b/src/Task/Run.php
@@ -4,10 +4,24 @@
use Cheppers\AssetJar\AssetJarAware;
use Cheppers\AssetJar\AssetJarAwareInterface;
+use Cheppers\LintReport\ReporterInterface;
+use Cheppers\LintReport\ReportWrapperInterface;
+use Cheppers\Robo\TsLint\LintReportWrapper\Json\ReportWrapper as JsonReportWrapper;
+use Cheppers\Robo\TsLint\LintReportWrapper\Yaml\ReportWrapper as YamlReportWrapper;
+use League\Container\ContainerAwareInterface;
+use League\Container\ContainerAwareTrait;
+use PackageVersions\Versions;
+use Robo\Common\BuilderAwareTrait;
use Robo\Common\IO;
+use Robo\Contract\BuilderAwareInterface;
+use Robo\Contract\OutputAwareInterface;
use Robo\Result;
use Robo\Task\BaseTask;
+use Robo\Task\Filesystem\loadTasks as FsLoadTasks;
+use Robo\Task\Filesystem\loadShortcuts as FsShortCuts;
+use Robo\TaskAccessor;
use Symfony\Component\Process\Process;
+use Symfony\Component\Yaml\Yaml;
/**
* Class TaskTsLintRun.
@@ -17,21 +31,40 @@
*
* @package Cheppers\Robo\TsLint\Task
*/
-class Run extends BaseTask implements AssetJarAwareInterface
+class Run extends BaseTask implements
+ AssetJarAwareInterface,
+ ContainerAwareInterface,
+ BuilderAwareInterface,
+ OutputAwareInterface
{
use AssetJarAware;
+ use ContainerAwareTrait;
+ use BuilderAwareTrait;
use IO;
+ use FsLoadTasks;
+ use FsShortCuts;
+ use TaskAccessor;
/**
* Exit code: No lints were found.
*/
const EXIT_CODE_OK = 0;
+ /**
+ * Lints with a severity of warning were reported (no errors).
+ */
+ const EXIT_CODE_WARNING = 1;
+
/**
* One or more errors were reported (and any number of warnings).
*/
- const EXIT_CODE_ERROR = 1;
+ const EXIT_CODE_ERROR = 2;
+
+ /**
+ * Something is invalid.
+ */
+ const EXIT_CODE_INVALID = 3;
/**
* @todo Some kind of dependency injection would be awesome.
@@ -111,6 +144,11 @@ class Run extends BaseTask implements AssetJarAwareInterface
*/
protected $format = '';
+ /**
+ * @var \Cheppers\LintReport\ReporterInterface[]
+ */
+ protected $lintReporters = [];
+
/**
* The location of a tsconfig.json file that will be used to determine which files will be linted.
*
@@ -153,7 +191,9 @@ class Run extends BaseTask implements AssetJarAwareInterface
*/
protected $exitMessages = [
0 => 'No lints were found',
- 1 => 'One or more errors were reported (and any number of warnings)',
+ 1 => 'Lints with a severity of warning were reported (no errors)',
+ 2 => 'One or more errors were reported (and any number of warnings)',
+ 3 => 'Extra lint reporters can be used only if the output format is "json".',
];
/**
@@ -222,6 +262,10 @@ public function options(array $options)
$this->format($value);
break;
+ case 'lintReporters':
+ $this->setLintReporters($value);
+ break;
+
case 'project':
$this->project($value);
break;
@@ -370,6 +414,51 @@ public function format($value)
return $this;
}
+ /**
+ * @return \Cheppers\LintReport\ReporterInterface[]
+ */
+ public function getLintReporters()
+ {
+ return $this->lintReporters;
+ }
+
+ /**
+ * @param array $lintReporters
+ *
+ * @return $this
+ */
+ public function setLintReporters(array $lintReporters)
+ {
+ $this->lintReporters = $lintReporters;
+
+ return $this;
+ }
+
+ /**
+ * @param string $id
+ * @param string|\Cheppers\LintReport\ReporterInterface $lintReporter
+ *
+ * @return $this
+ */
+ public function addLintReporter($id, $lintReporter = null)
+ {
+ $this->lintReporters[$id] = $lintReporter;
+
+ return $this;
+ }
+
+ /**
+ * @param string $id
+ *
+ * @return $this
+ */
+ public function removeLintReporter($id)
+ {
+ unset($this->lintReporters[$id]);
+
+ return $this;
+ }
+
/**
* @param string $value
*
@@ -454,54 +543,62 @@ protected function createIncludeList($items, $include)
public function run()
{
$command = $this->buildCommand();
-
$this->printTaskInfo(sprintf('TsLint task runs: %s', $command));
+ $lintReporters = $this->initLintReporters();
+ if ($lintReporters && !$this->isOutputFormatMachineReadable()) {
+ $this->exitCode = static::EXIT_CODE_INVALID;
+
+ return new Result($this, $this->exitCode, $this->getExitMessage($this->exitCode));
+ }
+
/** @var Process $process */
$process = new $this->processClass($command);
if ($this->workingDirectory) {
$process->setWorkingDirectory($this->workingDirectory);
}
+ $result = $this->prepareOutputDirectory();
+ if (!$result->wasSuccessful()) {
+ return $result;
+ }
+
$this->startTimer();
- $process->run();
+ $this->exitCode = $process->run();
$this->stopTimer();
- $this->exitCode = $process->getExitCode();
-
- $write_output = true;
-
- $report_parents = $this->getAssetJarMap('report');
- if ($this->hasAssetJar()
- && $report_parents
- && !$this->out
- && $this->format === 'yaml'
- && $this->convertFormatTo === 'yaml2jsonGroupByFiles'
- && in_array($this->exitCode, $this->lintSuccessExitCodes())
- ) {
- $report = json_decode($process->getOutput(), true);
- if ($report) {
- $this->exitCode = static::EXIT_CODE_ERROR;
+ $numOfErrors = $this->exitCode;
+ $numOfWarnings = 0;
+ if ($this->isLintSuccess()) {
+ $originalOutput = $process->getOutput();
+ if ($this->isOutputFormatMachineReadable()) {
+ $machineOutput = ($this->out ? file_get_contents($this->out) : $originalOutput);
+ $reportWrapper = $this->decodeOutput($machineOutput);
+ $numOfErrors = $reportWrapper->numOfErrors();
+ $numOfWarnings = $reportWrapper->numOfWarnings();
+
+ if ($this->isReportHasToBePutBackIntoJar()) {
+ $this->setAssetJarValue('report', $reportWrapper);
+ }
+
+ foreach ($lintReporters as $lintReporter) {
+ $lintReporter
+ ->setReportWrapper($reportWrapper)
+ ->generate();
+ }
}
- $write_output = false;
- $this
- ->getAssetJar()
- ->setValue($report_parents, $report);
- }
-
- if ($write_output) {
- $this->getOutput()->writeln($process->getOutput());
+ if (!$lintReporters) {
+ $this->output()->write($originalOutput);
+ }
}
- $message = isset($this->exitMessages[$this->exitCode]) ?
- $this->exitMessages[$this->exitCode]
- : $process->getErrorOutput();
+ $exitCode = $this->getTaskExitCode($numOfErrors, $numOfWarnings);
return new Result(
$this,
- $this->getTaskExitCode(),
- $message,
+ $exitCode,
+ $this->getExitMessage($exitCode) ?: $process->getErrorOutput(),
[
'time' => $this->getExecutionTime(),
]
@@ -592,25 +689,144 @@ public function buildCommand()
return vsprintf($cmd_pattern, $cmd_args);
}
+ /**
+ * @return bool
+ */
+ protected function isReportHasToBePutBackIntoJar()
+ {
+ return (
+ $this->hasAssetJar()
+ && $this->getAssetJarMap('report')
+ && $this->isLintSuccess()
+ );
+ }
+
+ /**
+ * @return bool
+ */
+ protected function isOutputFormatMachineReadable()
+ {
+ return ($this->format === 'yaml');
+ }
+
+ /**
+ * @param string $output
+ *
+ * @return ReportWrapperInterface
+ */
+ protected function decodeOutput($output)
+ {
+ $format = ($this->convertFormatTo === 'yaml2jsonGroupByFiles' ? 'json' : 'yaml');
+
+ switch ($format) {
+ case 'json':
+ return new JsonReportWrapper(json_decode($output, true));
+
+ case 'yaml':
+ if (function_exists('yaml_parse')) {
+ $decoded = yaml_parse($output);
+ } else {
+ $yamlVersion = ltrim(Versions::getShortVersion('symfony/yaml'), 'v');
+ if (version_compare($yamlVersion, '3.1.0', '>=')) {
+ $decoded = Yaml::parse($output, Yaml::PARSE_OBJECT_FOR_MAP);
+ } else {
+ $decoded = Yaml::parse($output);
+ }
+ }
+
+ return new YamlReportWrapper($decoded);
+ }
+
+ return null;
+ }
+
+ /**
+ * @return \Cheppers\LintReport\ReporterInterface[]
+ */
+ protected function initLintReporters()
+ {
+ $lintReporters = [];
+ $c = $this->getContainer();
+ foreach ($this->getLintReporters() as $id => $lintReporter) {
+ if ($lintReporter === false) {
+ continue;
+ }
+
+ if (!$lintReporter) {
+ $lintReporter = $c->get($id);
+ } elseif (is_string($lintReporter)) {
+ $lintReporter = $c->get($lintReporter);
+ }
+
+ if ($lintReporter instanceof ReporterInterface) {
+ $lintReporters[$id] = $lintReporter;
+ if (!$lintReporter->getDestination()) {
+ $lintReporter
+ ->setFilePathStyle('relative')
+ ->setDestination($this->output());
+ }
+ }
+ }
+
+ return $lintReporters;
+ }
+
/**
* Get the exit code regarding the failOn settings.
*
+ * @param int $numOfErrors
+ * @param int $numOfWarnings
+ *
* @return int
- * Exit code.
*/
- public function getTaskExitCode()
+ protected function getTaskExitCode($numOfErrors, $numOfWarnings)
{
- $tolerance = [
- 'never' => [static::EXIT_CODE_ERROR,],
- ];
+ if ($this->isLintSuccess()) {
+ switch ($this->failOn) {
+ case 'never':
+ return static::EXIT_CODE_OK;
+
+ case 'warning':
+ if ($numOfErrors) {
+ return static::EXIT_CODE_ERROR;
+ }
- if (isset($tolerance[$this->failOn]) && in_array($this->exitCode, $tolerance[$this->failOn])) {
- return static::EXIT_CODE_OK;
+ return $numOfWarnings ? static::EXIT_CODE_WARNING : static::EXIT_CODE_OK;
+
+ case 'error':
+ return $numOfErrors ? static::EXIT_CODE_ERROR : static::EXIT_CODE_OK;
+ }
}
return $this->exitCode;
}
+ /**
+ * @param int $exitCode
+ *
+ * @return string
+ */
+ protected function getExitMessage($exitCode)
+ {
+ if (isset($this->exitMessages[$exitCode])) {
+ return $this->exitMessages[$exitCode];
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns true if the lint ran successfully.
+ *
+ * Returns true even if there was any code style error or warning.
+ *
+ * @return bool
+ */
+ protected function isLintSuccess()
+ {
+ return in_array($this->exitCode, $this->lintSuccessExitCodes());
+ }
+
/**
* @return int[]
*/
@@ -618,7 +834,37 @@ protected function lintSuccessExitCodes()
{
return [
static::EXIT_CODE_OK,
+ static::EXIT_CODE_WARNING,
static::EXIT_CODE_ERROR,
];
}
+
+ /**
+ * Prepare directory for report outputs.
+ *
+ * @return null|\Robo\Result
+ * Returns NULL on success or an error \Robo\Result.
+ */
+ protected function prepareOutputDirectory()
+ {
+ if (empty($this->out)) {
+ return Result::success($this, 'There is no directory to create.');
+ }
+
+ $currentDir = getcwd();
+ if ($this->workingDirectory) {
+ chdir($this->workingDirectory);
+ }
+
+ $dir = pathinfo($this->out, PATHINFO_DIRNAME);
+ if (!file_exists($dir)) {
+ $result = $this->_mkdir($dir);
+ } else {
+ $result = Result::success($this, 'All directory was created successfully.');
+ }
+
+ chdir($currentDir);
+
+ return $result;
+ }
}
diff --git a/tests/_data/RoboFile.php b/tests/_data/RoboFile.php
index 0eb2d90..f231018 100644
--- a/tests/_data/RoboFile.php
+++ b/tests/_data/RoboFile.php
@@ -1,44 +1,88 @@
container = $container;
+
+ BaseReporter::lintReportConfigureContainer($this->container);
+
+ return $this;
+ }
/**
* @return \Cheppers\Robo\TsLint\Task\Run
*/
- public function lintVerbose()
+ public function lintStylishStdOutput()
{
return $this
->taskTsLintRun()
- ->setOutput($this->getOutput())
- ->format('verbose')
- ->paths(['samples/*']);
+ ->paths(['samples/*'])
+ ->format('stylish');
}
/**
* @return \Cheppers\Robo\TsLint\Task\Run
*/
- public function lintWithJar()
+ public function lintStylishFile()
{
- $assetJar = new \Cheppers\AssetJar\AssetJar([]);
-
return $this
->taskTsLintRun()
- ->setOutput($this->getOutput())
- ->setAssetJar($assetJar)
- ->setAssetJarMap('report', ['taskTsLint', 'report'])
- ->configFile('tslint.json')
- ->formattersDir('node_modules/tslint-formatters/lib/tslint/formatters')
+ ->paths(['samples/*'])
+ ->format('stylish')
+ ->out("{$this->reportsDir}/native.stylish.txt");
+ }
+
+ /**
+ * @return \Cheppers\Robo\TsLint\Task\Run
+ */
+ public function lintAllInOne()
+ {
+ $verboseFile = new VerboseReporter();
+ $verboseFile
+ ->setFilePathStyle('relative')
+ ->setDestination("{$this->reportsDir}/extra.verbose.txt");
+
+ $summaryFile = new SummaryReporter();
+ $summaryFile
+ ->setFilePathStyle('relative')
+ ->setDestination("{$this->reportsDir}/extra.summary.txt");
+
+ return $this->taskTsLintRun()
+ ->paths(['samples/*'])
->format('yaml')
->convertFormatTo('yaml2jsonGroupByFiles')
- ->paths(['samples/*']);
+ ->failOn('warning')
+ ->addLintReporter('verbose:StdOutput', 'lintVerboseReporter')
+ ->addLintReporter('verbose:file', $verboseFile)
+ ->addLintReporter('summary:StdOutput', 'lintSummaryReporter')
+ ->addLintReporter('summary:file', $summaryFile);
}
}
diff --git a/tests/_data/expected/extra.summary.txt b/tests/_data/expected/extra.summary.txt
new file mode 100644
index 0000000..d764668
--- /dev/null
+++ b/tests/_data/expected/extra.summary.txt
@@ -0,0 +1,14 @@
+samples/invalid-01.d.ts
++------------+-------------+
+| Source | Occurrences |
++------------+-------------+
+| whitespace | 1 |
++------------+-------------+
+
+samples/invalid-02.d.ts
++------------+-------------+
+| Source | Occurrences |
++------------+-------------+
+| one-line | 1 |
+| whitespace | 1 |
++------------+-------------+
diff --git a/tests/_data/expected/extra.verbose.txt b/tests/_data/expected/extra.verbose.txt
new file mode 100644
index 0000000..5b361db
--- /dev/null
+++ b/tests/_data/expected/extra.verbose.txt
@@ -0,0 +1,14 @@
+samples/invalid-01.d.ts
++----------+------+--------------------+
+| Severity | Line | Message |
++----------+------+--------------------+
+| error | 4 | missing whitespace |
++----------+------+--------------------+
+
+samples/invalid-02.d.ts
++----------+------+-------------------------+
+| Severity | Line | Message |
++----------+------+-------------------------+
+| error | 3 | misplaced opening brace |
+| error | 5 | missing whitespace |
++----------+------+-------------------------+
diff --git a/tests/_data/expected/native.stylish.txt b/tests/_data/expected/native.stylish.txt
new file mode 100644
index 0000000..bc5d392
--- /dev/null
+++ b/tests/_data/expected/native.stylish.txt
@@ -0,0 +1,6 @@
+samples/invalid-01.d.ts
+5:16 whitespace missing whitespace
+
+samples/invalid-02.d.ts
+4:5 one-line misplaced opening brace
+6:16 whitespace missing whitespace
diff --git a/tests/_data/samples/invalid-02.d.ts b/tests/_data/samples/invalid-02.d.ts
index b66788d..2b32223 100644
--- a/tests/_data/samples/invalid-02.d.ts
+++ b/tests/_data/samples/invalid-02.d.ts
@@ -1,6 +1,7 @@
declare namespace Foo2 {
- export interface IMyInterface01 {
+ export interface IMyInterface01
+ {
myProp:number;
diff --git a/tests/_support/AcceptanceTester.php b/tests/_support/AcceptanceTester.php
index 8ce6e7a..d57e77b 100644
--- a/tests/_support/AcceptanceTester.php
+++ b/tests/_support/AcceptanceTester.php
@@ -13,10 +13,10 @@
* @method void am($role)
* @method void lookForwardTo($achieveValue)
* @method void comment($description)
- * @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL)
+ * @method \Codeception\Lib\Friend haveFriend($name, $actorClass = null)
*
* @SuppressWarnings(PHPMD)
-*/
+ */
class AcceptanceTester extends \Codeception\Actor
{
use _generated\AcceptanceTesterActions;
@@ -26,7 +26,7 @@ class AcceptanceTester extends \Codeception\Actor
*/
public function clearTheReportsDir()
{
- $reportsDir = 'tests/_data/reports';
+ $reportsDir = codecept_data_dir('actual');
if (is_dir($reportsDir)) {
$finder = new \Symfony\Component\Finder\Finder();
$finder->in($reportsDir);
@@ -40,17 +40,67 @@ public function clearTheReportsDir()
/**
* @param string $taskName
+ * @param array $args
+ * @param array $options
*
* @return $this
*/
- public function runRoboTask($taskName)
+ public function runRoboTask($taskName, array $args = [], array $options = [])
{
- $cmd = sprintf(
- 'cd tests/_data && ../../bin/robo %s',
- escapeshellarg($taskName)
+ $cmdPattern = 'cd %s && ../../bin/robo %s';
+ $cmdArgs = [
+ escapeshellarg(codecept_data_dir()),
+ escapeshellarg($taskName),
+ ];
+
+ foreach ($options as $option => $value) {
+ $cmdPattern .= " --$option";
+ if ($value !== null) {
+ $cmdPattern .= '=%s';
+ $cmdArgs[] = escapeshellarg($value);
+ }
+ }
+
+ $cmdPattern .= str_repeat(' %s', count($args));
+ foreach ($args as $arg) {
+ $cmdArgs[] = escapeshellarg($arg);
+ }
+
+ $this->runShellCommand(vsprintf($cmdPattern, $cmdArgs));
+
+ return $this;
+ }
+
+ /**
+ * @param string $fileName
+ *
+ * @return $this
+ */
+ public function haveAFileLikeThis($fileName) {
+ $expectedDir = codecept_data_dir('expected');
+ $actualDir = codecept_data_dir('actual');
+
+ Assert::assertContains(
+ file_get_contents("$expectedDir/$fileName"),
+ file_get_contents("$actualDir/$fileName")
);
- $this->runShellCommand($cmd);
+ return $this;
+ }
+
+ /**
+ * @param string $fileName
+ *
+ * @return $this
+ */
+ public function haveAValidCheckstyleReport($fileName)
+ {
+ $fileName = codecept_data_dir($fileName);
+ $doc = new \DOMDocument();
+ $doc->loadXML(file_get_contents($fileName));
+ $xpath = new DOMXPath($doc);
+ $rootElement = $xpath->query('/checkstyle');
+ Assert::assertEquals(1, $rootElement->length, 'Root element of the Checkstyle XML is exists.');
return $this;
}
@@ -84,7 +134,7 @@ public function seeThisTextInTheStdError($expected)
*
* @return $this
*/
- public function theExitCodeShouldBe($expected)
+ public function expectTheExitCodeToBe($expected)
{
Assert::assertEquals($expected, $this->getExitCode());
diff --git a/tests/acceptance/LintAllInOneCept.php b/tests/acceptance/LintAllInOneCept.php
new file mode 100644
index 0000000..7c9b49c
--- /dev/null
+++ b/tests/acceptance/LintAllInOneCept.php
@@ -0,0 +1,20 @@
+wantTo("Run Robo task '$roboTaskName'.");
+$i
+ ->clearTheReportsDir()
+ ->runRoboTask($roboTaskName)
+ ->expectTheExitCodeToBe(2)
+ ->seeThisTextInTheStdOutput(file_get_contents("$expectedDir/extra.verbose.txt"))
+ ->seeThisTextInTheStdOutput(file_get_contents("$expectedDir/extra.summary.txt"))
+ ->haveAFileLikeThis('extra.verbose.txt')
+ ->haveAFileLikeThis('extra.summary.txt')
+ ->seeThisTextInTheStdError('One or more errors were reported (and any number of warnings)');
diff --git a/tests/acceptance/LintStylishFileCept.php b/tests/acceptance/LintStylishFileCept.php
new file mode 100644
index 0000000..d405a3e
--- /dev/null
+++ b/tests/acceptance/LintStylishFileCept.php
@@ -0,0 +1,16 @@
+wantTo("Run Robo task '$roboTaskName'.");
+$i
+ ->clearTheReportsDir()
+ ->runRoboTask($roboTaskName)
+ ->expectTheExitCodeToBe(2)
+ ->haveAFileLikeThis('native.stylish.txt')
+ ->seeThisTextInTheStdError('One or more errors were reported (and any number of warnings)');
diff --git a/tests/acceptance/LintStylishStdOutputCept.php b/tests/acceptance/LintStylishStdOutputCept.php
new file mode 100644
index 0000000..b7288ce
--- /dev/null
+++ b/tests/acceptance/LintStylishStdOutputCept.php
@@ -0,0 +1,17 @@
+wantTo("Run Robo task '$roboTaskName'.");
+$i
+ ->clearTheReportsDir()
+ ->runRoboTask($roboTaskName)
+ ->expectTheExitCodeToBe(2)
+ ->seeThisTextInTheStdOutput(file_get_contents("$expectedDir/native.stylish.txt"))
+ ->seeThisTextInTheStdError('One or more errors were reported (and any number of warnings)');
diff --git a/tests/acceptance/LintVerboseCept.php b/tests/acceptance/LintVerboseCept.php
deleted file mode 100644
index a1fcaa6..0000000
--- a/tests/acceptance/LintVerboseCept.php
+++ /dev/null
@@ -1,13 +0,0 @@
-wantTo('tslint --format verbose');
-
-$i->runRoboTask('lint:verbose');
-$i->theExitCodeShouldBe(2);
-$i->seeThisTextInTheStdOutput('(whitespace) samples/invalid-01.d.ts[5, 16]: missing whitespace');
-$i->seeThisTextInTheStdOutput('(whitespace) samples/invalid-02.d.ts[5, 16]: missing whitespace');
diff --git a/tests/acceptance/LintWithJarCept.php b/tests/acceptance/LintWithJarCept.php
deleted file mode 100644
index 37c2e81..0000000
--- a/tests/acceptance/LintWithJarCept.php
+++ /dev/null
@@ -1,11 +0,0 @@
-wantTo('tslint --format yaml | tslint-formatters yaml2jsonGroupByFiles');
-$i->runRoboTask('lint:with-jar');
-$i->theExitCodeShouldBe(1);
-$i->seeThisTextInTheStdError('One or more errors were reported (and any number of warnings)');
diff --git a/tests/unit/LintReportWrapper/JsonReportWrapperTest.php b/tests/unit/LintReportWrapper/JsonReportWrapperTest.php
new file mode 100644
index 0000000..18ba356
--- /dev/null
+++ b/tests/unit/LintReportWrapper/JsonReportWrapperTest.php
@@ -0,0 +1,186 @@
+ [
+ 'expected' => [
+ 'countFiles' => 0,
+ 'numOfErrors' => 0,
+ 'numOfWarnings' => 0,
+ 'highestSeverity' => 'ok',
+ ],
+ 'report' => [],
+ 'filesStats' => [],
+ ],
+ 'ok:one-file' => [
+ 'expected' => [
+ 'countFiles' => 1,
+ 'numOfErrors' => 0,
+ 'numOfWarnings' => 0,
+ 'highestSeverity' => 'ok',
+ ],
+ 'report' => [
+ 'a.ts' => [],
+ ],
+ 'filesStats' => [
+ 'a.ts' => [
+ 'numOfErrors' => 0,
+ 'numOfWarnings' => 0,
+ 'highestSeverity' => 'ok',
+ 'stats' => [
+ 'severity' => 'ok',
+ 'has' => [
+ 'ok' => false,
+ 'warning' => false,
+ 'error' => false,
+ ],
+ 'source' => [],
+ ],
+ ],
+ ],
+ ],
+ 'warning:one-file' => [
+ 'expected' => [
+ 'countFiles' => 1,
+ 'numOfErrors' => 0,
+ 'numOfWarnings' => 1,
+ 'highestSeverity' => 'warning',
+ ],
+ 'report' => [
+ 'a.ts' => [
+ [
+ 'severity' => 'warning',
+ 'source' => 's1',
+ 'line' => 1,
+ 'column' => 2,
+ 'message' => 'm1',
+ ]
+ ],
+ ],
+ 'filesStats' => [
+ 'a.ts' => [
+ 'numOfErrors' => 0,
+ 'numOfWarnings' => 1,
+ 'highestSeverity' => 'warning',
+ 'stats' => [
+ 'severity' => 'warning',
+ 'has' => [
+ 'ok' => false,
+ 'warning' => true,
+ 'error' => false,
+ ],
+ 'source' => [
+ 's1' => [
+ 'severity' => 'warning',
+ 'count' => 1,
+ ],
+ ],
+ ],
+ ],
+ ],
+ ],
+ 'error:one-file' => [
+ 'expected' => [
+ 'countFiles' => 1,
+ 'numOfErrors' => 1,
+ 'numOfWarnings' => 0,
+ 'highestSeverity' => 'error',
+ ],
+ 'report' => [
+ 'a.ts' => [
+ [
+ 'severity' => 'error',
+ 'source' => 's1',
+ 'line' => 1,
+ 'column' => 2,
+ 'message' => 'm1',
+ ]
+ ],
+ ],
+ 'filesStats' => [
+ 'a.ts' => [
+ 'numOfErrors' => 1,
+ 'numOfWarnings' => 0,
+ 'highestSeverity' => 'error',
+ 'stats' => [
+ 'severity' => 'error',
+ 'has' => [
+ 'ok' => false,
+ 'warning' => false,
+ 'error' => true,
+ ],
+ 'source' => [
+ 's1' => [
+ 'severity' => 'error',
+ 'count' => 1,
+ ],
+ ],
+ ],
+ ],
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider casesReports
+ *
+ * @param array $expected
+ * @param array $report
+ * @param array $filesStats
+ */
+ public function testAll(array $expected, array $report, array $filesStats)
+ {
+ $rw = new ReportWrapper($report);
+
+ $this->assertEquals($expected['countFiles'], $rw->countFiles());
+ $this->assertEquals($expected['numOfErrors'], $rw->numOfErrors());
+ $this->assertEquals($expected['numOfWarnings'], $rw->numOfWarnings());
+ $this->assertEquals($expected['highestSeverity'], $rw->highestSeverity());
+
+ /**
+ * @var string $filePath
+ * @var \Cheppers\Robo\TsLint\LintReportWrapper\Json\FileWrapper $fw
+ */
+ foreach ($rw->yieldFiles() as $filePath => $fw) {
+ $fileStats = $filesStats[$filePath];
+ $this->assertEquals($filePath, $fw->filePath());
+ $this->assertEquals($fileStats['numOfErrors'], $fw->numOfErrors());
+ $this->assertEquals($fileStats['numOfWarnings'], $fw->numOfWarnings());
+ $this->assertEquals($fileStats['highestSeverity'], $fw->highestSeverity());
+ $this->assertEquals($fileStats['stats'], $fw->stats());
+
+ /**
+ * @var int $i
+ * @var \Cheppers\LintReport\FailureWrapperInterface $failureWrapper
+ */
+ foreach ($fw->yieldFailures() as $i => $failureWrapper) {
+ $failure = $report[$filePath][$i];
+ $this->assertEquals($failure['severity'], $failureWrapper->severity());
+ $this->assertEquals($failure['source'], $failureWrapper->source());
+ $this->assertEquals($failure['line'], $failureWrapper->line());
+ $this->assertEquals($failure['column'], $failureWrapper->column());
+ $this->assertEquals($failure['message'], $failureWrapper->message());
+ }
+ }
+ }
+}
diff --git a/tests/unit/LintReportWrapper/YamlReportWrapperTest.php b/tests/unit/LintReportWrapper/YamlReportWrapperTest.php
new file mode 100644
index 0000000..38a982f
--- /dev/null
+++ b/tests/unit/LintReportWrapper/YamlReportWrapperTest.php
@@ -0,0 +1,184 @@
+ [
+ 'expected' => [
+ 'countFiles' => 0,
+ 'numOfErrors' => 0,
+ 'numOfWarnings' => 0,
+ 'highestSeverity' => 'ok',
+ ],
+ 'report' => [],
+ 'filesStats' => [],
+ ],
+ 'warning:one-file' => [
+ 'expected' => [
+ 'countFiles' => 1,
+ 'numOfErrors' => 0,
+ 'numOfWarnings' => 1,
+ 'highestSeverity' => 'warning',
+ ],
+ 'report' => [
+ [
+ 'failures' => [
+ [
+ 'name' => 'a.ts',
+ 'severity' => 'warning',
+ 'ruleName' => 'r1',
+ 'failure' => 'f1',
+ 'startPosition' => [
+ 'line' => 1,
+ 'character' => 2,
+ 'position' => 3,
+ ],
+ 'endPosition' => [
+ 'line' => 4,
+ 'character' => 5,
+ 'position' => 6,
+ ],
+ ]
+ ],
+ ],
+ ],
+ 'filesStats' => [
+ 'a.ts' => [
+ 'numOfErrors' => 0,
+ 'numOfWarnings' => 1,
+ 'highestSeverity' => 'warning',
+ 'stats' => [
+ 'severity' => 'warning',
+ 'has' => [
+ 'ok' => false,
+ 'warning' => true,
+ 'error' => false,
+ ],
+ 'source' => [
+ 'r1' => [
+ 'severity' => 'warning',
+ 'count' => 1,
+ ],
+ ],
+ ],
+ ],
+ ],
+ ],
+ 'error:one-file' => [
+ 'expected' => [
+ 'countFiles' => 1,
+ 'numOfErrors' => 1,
+ 'numOfWarnings' => 0,
+ 'highestSeverity' => 'error',
+ ],
+ 'report' => [
+ [
+ 'failures' => [
+ [
+ 'name' => 'a.ts',
+ 'severity' => 'error',
+ 'ruleName' => 'r1',
+ 'failure' => 'f1',
+ 'startPosition' => [
+ 'line' => 1,
+ 'character' => 2,
+ 'position' => 3,
+ ],
+ 'endPosition' => [
+ 'line' => 4,
+ 'character' => 5,
+ 'position' => 6,
+ ],
+ ]
+ ],
+ ],
+ ],
+ 'filesStats' => [
+ 'a.ts' => [
+ 'numOfErrors' => 1,
+ 'numOfWarnings' => 0,
+ 'highestSeverity' => 'error',
+ 'stats' => [
+ 'severity' => 'error',
+ 'has' => [
+ 'ok' => false,
+ 'warning' => false,
+ 'error' => true,
+ ],
+ 'source' => [
+ 'r1' => [
+ 'severity' => 'error',
+ 'count' => 1,
+ ],
+ ],
+ ],
+ ],
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider casesReports
+ *
+ * @param array $expected
+ * @param array $report
+ * @param array $filesStats
+ */
+ public function testAll(array $expected, array $report, array $filesStats)
+ {
+ $rw = new ReportWrapper($report);
+
+ $this->assertEquals($expected['countFiles'], $rw->countFiles());
+ $this->assertEquals($expected['numOfErrors'], $rw->numOfErrors());
+ $this->assertEquals($expected['numOfWarnings'], $rw->numOfWarnings());
+ $this->assertEquals($expected['highestSeverity'], $rw->highestSeverity());
+
+ $docIndex = -1;
+ /**
+ * @var string $filePath
+ * @var \Cheppers\Robo\TsLint\LintReportWrapper\Json\FileWrapper $fw
+ */
+ foreach ($rw->yieldFiles() as $fw) {
+ $docIndex++;
+ $filePath = $fw->filePath();
+ $fileStats = $filesStats[$filePath];
+ $this->assertEquals($filePath, $fw->filePath());
+ $this->assertEquals($fileStats['numOfErrors'], $fw->numOfErrors());
+ $this->assertEquals($fileStats['numOfWarnings'], $fw->numOfWarnings());
+ $this->assertEquals($fileStats['highestSeverity'], $fw->highestSeverity());
+ $this->assertEquals($fileStats['stats'], $fw->stats());
+
+ /**
+ * @var int $i
+ * @var \Cheppers\LintReport\FailureWrapperInterface $failureWrapper
+ */
+ foreach ($fw->yieldFailures() as $i => $failureWrapper) {
+ $failure = $report[$docIndex]['failures'][$i];
+ $this->assertEquals($failure['severity'], $failureWrapper->severity());
+ $this->assertEquals($failure['ruleName'], $failureWrapper->source());
+ $this->assertEquals($failure['startPosition']['line'], $failureWrapper->line());
+ $this->assertEquals($failure['startPosition']['character'], $failureWrapper->column());
+ $this->assertEquals($failure['failure'], $failureWrapper->message());
+ }
+ }
+ }
+}
diff --git a/tests/unit/Task/RunTest.php b/tests/unit/Task/RunTest.php
index f5b970d..d1b1812 100644
--- a/tests/unit/Task/RunTest.php
+++ b/tests/unit/Task/RunTest.php
@@ -1,7 +1,9 @@
getMethod($name);
+ $method->setAccessible(true);
+
+ return $method;
+ }
+
/**
* @var \League\Container\Container
*/
@@ -38,6 +54,28 @@ public function getContainer()
return $this->container;
}
+ public function testGetSetLintReporters()
+ {
+ $task = new RunTask([
+ 'lintReporters' => [
+ 'aKey' => 'aValue',
+ ],
+ ]);
+
+ $task
+ ->addLintReporter('bKey', 'bValue')
+ ->addLintReporter('cKey', 'cValue')
+ ->removeLintReporter('bKey');
+
+ $this->assertEquals(
+ [
+ 'aKey' => 'aValue',
+ 'cKey' => 'cValue',
+ ],
+ $task->getLintReporters()
+ );
+ }
+
/**
* @return array
*/
@@ -219,14 +257,16 @@ public function casesBuildCommand()
*/
public function testBuildCommand($expected, array $options, array $paths)
{
- $tslint = new Run($options, $paths);
+ $tslint = new RunTask($options, $paths);
static::assertEquals($expected, $tslint->buildCommand());
}
public function testExitCodeConstants()
{
- static::assertEquals(0, Run::EXIT_CODE_OK);
- static::assertEquals(1, Run::EXIT_CODE_ERROR);
+ static::assertEquals(0, RunTask::EXIT_CODE_OK);
+ static::assertEquals(1, RunTask::EXIT_CODE_WARNING);
+ static::assertEquals(2, RunTask::EXIT_CODE_ERROR);
+ static::assertEquals(3, RunTask::EXIT_CODE_INVALID);
}
/**
@@ -234,49 +274,71 @@ public function testExitCodeConstants()
*/
public function casesGetTaskExitCode()
{
+ $o = RunTask::EXIT_CODE_OK;
+ $w = RunTask::EXIT_CODE_WARNING;
+ $e = RunTask::EXIT_CODE_ERROR;
+ $u = 5;
+
return [
- 'never-ok' => [
- Run::EXIT_CODE_OK,
- [
- 'failOn' => 'never',
- ],
- Run::EXIT_CODE_OK,
- ],
- 'never-error' => [
- Run::EXIT_CODE_OK,
- [
- 'failOn' => 'never',
- ],
- Run::EXIT_CODE_ERROR,
- ],
- 'warning-ok' => [
- Run::EXIT_CODE_OK,
- [
- 'failOn' => 'warning',
- ],
- Run::EXIT_CODE_OK,
- ],
- 'warning-error' => [
- Run::EXIT_CODE_ERROR,
- [
- 'failOn' => 'warning',
- ],
- Run::EXIT_CODE_ERROR,
- ],
- 'error-ok' => [
- Run::EXIT_CODE_OK,
- [
- 'failOn' => 'error',
- ],
- Run::EXIT_CODE_OK,
- ],
- 'error-error' => [
- Run::EXIT_CODE_ERROR,
- [
- 'failOn' => 'error',
- ],
- Run::EXIT_CODE_ERROR,
- ],
+ 'never-000' => [$o, 'never', 0, 0, 0],
+ 'never-001' => [$o, 'never', 0, 0, 1],
+ 'never-002' => [$o, 'never', 0, 0, 2],
+ 'never-005' => [$u, 'never', 0, 0, 5],
+
+ 'never-010' => [$o, 'never', 0, 1, 0],
+ 'never-011' => [$o, 'never', 0, 1, 1],
+ 'never-012' => [$o, 'never', 0, 1, 2],
+ 'never-015' => [$u, 'never', 0, 1, 5],
+
+ 'never-100' => [$o, 'never', 1, 0, 0],
+ 'never-101' => [$o, 'never', 1, 0, 1],
+ 'never-102' => [$o, 'never', 1, 0, 2],
+ 'never-105' => [$u, 'never', 1, 0, 5],
+
+ 'never-110' => [$o, 'never', 1, 1, 0],
+ 'never-111' => [$o, 'never', 1, 1, 1],
+ 'never-112' => [$o, 'never', 1, 1, 2],
+ 'never-115' => [$u, 'never', 1, 1, 5],
+
+ 'warning-000' => [$o, 'warning', 0, 0, 0],
+ 'warning-001' => [$o, 'warning', 0, 0, 1],
+ 'warning-002' => [$o, 'warning', 0, 0, 2],
+ 'warning-005' => [$u, 'warning', 0, 0, 5],
+
+ 'warning-010' => [$w, 'warning', 0, 1, 0],
+ 'warning-011' => [$w, 'warning', 0, 1, 1],
+ 'warning-012' => [$w, 'warning', 0, 1, 2],
+ 'warning-015' => [$u, 'warning', 0, 1, 5],
+
+ 'warning-100' => [$e, 'warning', 1, 0, 0],
+ 'warning-101' => [$e, 'warning', 1, 0, 1],
+ 'warning-102' => [$e, 'warning', 1, 0, 2],
+ 'warning-105' => [$u, 'warning', 1, 0, 5],
+
+ 'warning-110' => [$e, 'warning', 1, 1, 0],
+ 'warning-111' => [$e, 'warning', 1, 1, 1],
+ 'warning-112' => [$e, 'warning', 1, 1, 2],
+ 'warning-115' => [$u, 'warning', 1, 1, 5],
+
+ 'error-000' => [$o, 'error', 0, 0, 0],
+ 'error-001' => [$o, 'error', 0, 0, 1],
+ 'error-002' => [$o, 'error', 0, 0, 2],
+ 'error-005' => [$u, 'error', 0, 0, 5],
+
+ 'error-010' => [$o, 'error', 0, 1, 0],
+ 'error-011' => [$o, 'error', 0, 1, 1],
+ 'error-012' => [$o, 'error', 0, 1, 2],
+ 'error-015' => [$u, 'error', 0, 1, 5],
+
+ 'error-100' => [$e, 'error', 1, 0, 0],
+ 'error-101' => [$e, 'error', 1, 0, 1],
+ 'error-102' => [$e, 'error', 1, 0, 2],
+ 'error-105' => [$u, 'error', 1, 0, 5],
+
+ 'error-110' => [$e, 'error', 1, 1, 0],
+ 'error-111' => [$e, 'error', 1, 1, 1],
+ 'error-112' => [$e, 'error', 1, 1, 2],
+ 'error-115' => [$u, 'error', 1, 1, 5],
];
}
@@ -284,19 +346,24 @@ public function casesGetTaskExitCode()
* @dataProvider casesGetTaskExitCode
*
* @param int $expected
- * @param array $options
- * @param int $exit_code
+ * @param string $failOn
+ * @param int $numOfErrors
+ * @param int $numOfWarnings
+ * @param int $exitCode
*/
- public function testGetTaskExitCode($expected, $options, $exit_code)
+ public function testGetTaskExitCode($expected, $failOn, $numOfErrors, $numOfWarnings, $exitCode)
{
- /** @var Run $scss_lint */
- $scss_lint = Stub::construct(
- Run::class,
- [$options, []],
- ['exitCode' => $exit_code]
+ /** @var RunTask $runTask */
+ $runTask = Stub::construct(
+ RunTask::class,
+ [['failOn' => $failOn]],
+ ['exitCode' => $exitCode]
);
- static::assertEquals($expected, $scss_lint->getTaskExitCode());
+ static::assertEquals(
+ $expected,
+ static::getMethod('getTaskExitCode')->invokeArgs($runTask, [$numOfErrors, $numOfWarnings])
+ );
}
/**
@@ -305,19 +372,58 @@ public function testGetTaskExitCode($expected, $options, $exit_code)
public function casesRun()
{
return [
- 'without asset jar' => [
+ 'withoutJar - success' => [
0,
- 'my-dummy-output',
+ [],
+ false,
+ ],
+ 'withoutJar - warning' => [
+ 1,
+ [
+ 'a.ts' => [
+ [
+ 'severity' => 'warning',
+ ],
+ ],
+ ],
+ false,
+ ],
+ 'withoutJar - error' => [
+ 2,
+ [
+ 'a.ts' => [
+ [
+ 'severity' => 'error',
+ ],
+ ]
+ ],
false,
],
- 'with_asset_jar-success' => [
+ 'withJar - success' => [
0,
[],
true,
],
- 'with_asset_jar-fail' => [
+ 'withJar - warning' => [
1,
- ['file-01.ts' => []],
+ [
+ 'a.ts' => [
+ [
+ 'severity' => 'warning',
+ ],
+ ],
+ ],
+ true,
+ ],
+ 'withJar - error' => [
+ 2,
+ [
+ 'a.ts' => [
+ [
+ 'severity' => 'error',
+ ],
+ ],
+ ],
true,
],
];
@@ -328,99 +434,113 @@ public function casesRun()
*
* @dataProvider casesRun
*
- * @param int $exit_code
- * @param string $stdOutput
+ * @param int $expectedExitCode
+ * @param array $expectedReport
* @param bool $withJar
*/
- public function testRunSuccess($exit_code, $stdOutput, $withJar)
+ public function testRun($expectedExitCode, array $expectedReport, $withJar)
{
$options = [
'workingDirectory' => 'my-working-dir',
'assetJarMapping' => ['report' => ['tsLintRun', 'report']],
'format' => 'yaml',
+ 'failOn' => 'warning',
'convertFormatTo' => 'yaml2jsonGroupByFiles',
];
- /** @var Run $task */
- $task = Stub::construct(
- Run::class,
+ /** @var RunTask $runTask */
+ $runTask = Stub::construct(
+ RunTask::class,
[$options, []],
[
- 'processClass' => \Helper\Dummy\Process::class,
+ 'processClass' => DummyProcess::class,
]
);
$output = new \Helper\Dummy\Output();
- \Helper\Dummy\Process::$exitCode = $exit_code;
- \Helper\Dummy\Process::$stdOutput = $withJar ? json_encode($stdOutput) : $stdOutput;
+ DummyProcess::$exitCode = $expectedExitCode;
+ DummyProcess::$stdOutput = json_encode($expectedReport);
- $task->setConfig(Robo::config());
- $task->setLogger($this->container->get('logger'));
- $task->setOutput($output);
+ $runTask->setLogger($this->container->get('logger'));
+ $runTask->setOutput($output);
$assetJar = null;
if ($withJar) {
- $assetJar = new \Cheppers\AssetJar\AssetJar();
- $task->setAssetJar($assetJar);
+ $assetJar = new AssetJar();
+ $runTask->setAssetJar($assetJar);
}
- $result = $task->run();
+ $result = $runTask->run();
- static::assertEquals($exit_code, $result->getExitCode());
+ static::assertEquals($expectedExitCode, $result->getExitCode(), 'Exit code');
static::assertEquals(
$options['workingDirectory'],
- \Helper\Dummy\Process::$instance->getWorkingDirectory()
+ DummyProcess::$instance->getWorkingDirectory(),
+ 'Working directory'
);
if ($withJar) {
+ /** @var \Cheppers\LintReport\ReportWrapperInterface $reportWrapper */
+ $reportWrapper = $assetJar->getValue(['tsLintRun', 'report']);
static::assertEquals(
- $stdOutput,
- $assetJar->getValue(['tsLintRun', 'report'])
+ $expectedReport,
+ $reportWrapper->getReport(),
+ 'Output equals with jar'
);
} else {
- static::assertContains(
- $stdOutput,
- $output->output,
- 'Output contains'
+ static::assertEquals(
+ $expectedReport,
+ json_decode($output->output, true),
+ 'Output equals without jar'
);
}
}
public function testRunFailed()
{
- $exit_code = 1;
- $std_output = '{"foo": "bar"}';
+ $exitCode = 1;
+ $expectedReport = [
+ 'a.ts' => [
+ [
+ 'severity' => 'warning',
+ ],
+ ],
+ ];
+ $expectedReportJson = json_encode($expectedReport);
$options = [
'workingDirectory' => 'my-working-dir',
'assetJarMapping' => ['report' => ['tsLintRun', 'report']],
+ 'failOn' => 'warning',
'format' => 'yaml',
'convertFormatTo' => 'yaml2jsonGroupByFiles',
];
- /** @var Run $task */
+ /** @var RunTask $task */
$task = Stub::construct(
- Run::class,
+ RunTask::class,
[$options, []],
[
- 'processClass' => \Helper\Dummy\Process::class,
+ 'processClass' => DummyProcess::class,
]
);
- \Helper\Dummy\Process::$exitCode = $exit_code;
- \Helper\Dummy\Process::$stdOutput = $std_output;
+ DummyProcess::$exitCode = $exitCode;
+ DummyProcess::$stdOutput = $expectedReportJson;
$task->setConfig(Robo::config());
$task->setLogger($this->container->get('logger'));
- $asset_jar = new \Cheppers\AssetJar\AssetJar();
- $task->setAssetJar($asset_jar);
+ $assetJar = new AssetJar();
+ $task->setAssetJar($assetJar);
$result = $task->run();
- static::assertEquals($exit_code, $result->getExitCode());
+ static::assertEquals($exitCode, $result->getExitCode());
static::assertEquals(
$options['workingDirectory'],
- \Helper\Dummy\Process::$instance->getWorkingDirectory()
+ DummyProcess::$instance->getWorkingDirectory()
);
- static::assertEquals(['foo' => 'bar'], $asset_jar->getValue(['tsLintRun', 'report']));
+ /** @var \Cheppers\LintReport\ReportWrapperInterface $reportWrapper */
+ $reportWrapper = $assetJar->getValue(['tsLintRun', 'report']);
+ static::assertEquals($expectedReport, $reportWrapper->getReport());
}
}