diff --git a/.phpspec/class.tpl b/.phpspec/class.tpl
new file mode 100644
index 0000000..af55bd5
--- /dev/null
+++ b/.phpspec/class.tpl
@@ -0,0 +1,16 @@
+
+ * @copyright 2013-2016 Hexmedia.pl
+ * @license @see LICENSE
+ */%namespace_block%
+
+/**
+ * Class Application
+ *
+ * @package %namespace%
+ */
+class %name%
+{
+}
diff --git a/.sensiolabs.yml b/.sensiolabs.yml
index 5a23935..dd1cf0b 100644
--- a/.sensiolabs.yml
+++ b/.sensiolabs.yml
@@ -1,6 +1,7 @@
global_exclude_dirs:
- vendor
- Tests
+ - src-dev
rules:
git.user_specific_ignored_file:
diff --git a/.travis.yml b/.travis.yml
index 5a04b47..8d91ead 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -29,7 +29,6 @@ matrix:
allow_failures:
- env: DEPS='dev'
- php: nightly
- - php: 7.0
before_install:
- if [ "$TRAVIS_PHP_VERSION" != "hhvm" ]; then cat $HOME/.phpenv/versions/$TRAVIS_PHP_VERSION/etc/conf.d/xdebug.ini > ./xdebug.ini ; fi
@@ -45,6 +44,7 @@ before_install:
- echo '#!/bin/bash' > install.sh
- echo -n "composer update" >> install.sh
- echo -n " --prefer-dist" >> install.sh
+ - 'if [ "$TRAVIS_PHP_VERSION" == "7.0" ] || [ "$TRAVIS_PHP_VERSION" == "nightly" ]; then cat composer.json | sed -e "$(cat composer.json | grep -n "phpspec/phpspec\": \"~2.4\"" | cut -f1 -d:)s/.*/\"phpspec\/phpspec\": \"~2.5@dev\",/" > composer.json; fi'
- if [ "$DEPS" == "low" ]; then echo -n " --prefer-lowest" >> install.sh; fi;
- if [ "$DEPS" == "normal" ]; then echo -n " --prefer-stable" >> install.sh; fi;
- sed -n '/prefer-stable/!p' composer.json > tmp.json && mv tmp.json composer.json;
diff --git a/TODO.md b/TODO.md
index 95f6b21..f40ee44 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,19 +1,24 @@
+Tests:
+------
+* Configure at least one osx(travis) environment to test if it is working on osx.
+
This version
------------
* System reader should also use factory.
-* Read should be done always via System/*.php (eg. for Unix System/Unix.php)
-* Configure at least one osx(travis) environment to test if it is working on osx.
+* Readers needs to be checked and refactored
* Check names of all systems that should be supported. All Unix like.
-* Add phpspec to existing commands
+* Add specs to existing commands
* Try integration with Symfony CrontabBundle. This will need some commands to be rewritten
-* Write behat tests
* Unify exception names.
+* Change beforeComment to comment
+* Add protection for special strings in unix, if they exists, this should not work.
Next Versions
-------------
-* support for windows Tasks (more info: http://stackoverflow.com/questions/132971/what-is-the-windows-version-of-cron, https://msdn.microsoft.com/en-us/library/windows/desktop/bb736357(v=vs.85).aspx)
-* support for special strings in unix cron (only reading will be enough i think), and possibility to setup cron for startup.
-* create comment object that can be added to task or variable
+-------------
+* support for special strings in unix cron, and possibility to setup cron for startup.
* support for comments in variables, currently, all comments between variables will be ignored, and removed.
-* Why appveyor is not resulting in error after runing travis
* add support for importing tasks from crontab to file, should be interactive command.
+
+In future
+---------
+* support for windows Tasks (more info: http://stackoverflow.com/questions/132971/what-is-the-windows-version-of-cron, https://msdn.microsoft.com/en-us/library/windows/desktop/bb736357(v=vs.85).aspx)
diff --git a/Tests/example_configurations/empty.xml b/Tests/example_configurations/empty.xml
new file mode 100755
index 0000000..4ce5b31
--- /dev/null
+++ b/Tests/example_configurations/empty.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/Tests/example_configurations/test.ini b/Tests/example_configurations/test.ini
index 0d09392..621d285 100755
--- a/Tests/example_configurations/test.ini
+++ b/Tests/example_configurations/test.ini
@@ -22,3 +22,11 @@ machine = www103
variables.MAILTO = test@test.com
variables.NO_VALIDATE = true
+[command_without_log_file]
+command = ./some/command_without_log_file
+minute = *
+hour = *
+day_of_month = *
+day_of_week = *
+month = *
+machine = www103
diff --git a/Tests/example_configurations/test.json b/Tests/example_configurations/test.json
index 1086705..f86220d 100755
--- a/Tests/example_configurations/test.json
+++ b/Tests/example_configurations/test.json
@@ -1,29 +1,40 @@
{
- "s3_synchronize": {
- "command": "mwe:photo:s3 asgasg afasf",
+ "command1": {
+ "command": "./some/command1",
"minute": "*/13",
"hour": "*",
"day_of_month": "*",
"day_of_week": "*",
"month": "*",
- "log_file": "./logs/schema_validate.log",
+ "log_file": "./logs/some_log1.log",
"machine": "www*",
+ "comment": "this is some comment for this crontab",
"variables": {
- "MAILTO": "k.kuczek@tvn.pl"
+ "MAILTO": "test@test.pl"
}
},
- "s3_synchronize2": {
- "command": "mwe:photo:s3 asgasg afasf",
+ "command2": {
+ "command": "./some/command2",
"minute": "*",
"hour": "*",
"day_of_month": "*",
"day_of_week": "*",
"month": "*",
- "log_file": "./logs/schema_validate.log",
+ "log_file": "./logs/some_log2.log",
"machine": "www103",
"variables": {
- "MAILTO": "j.zieba@tvn.pl"
+ "MAILTO": "test@test.com",
+ "NO_VALIDATE": true
}
+ },
+ "command_without_log_file": {
+ "command": "./some/command_without_log_file",
+ "minute": "*",
+ "hour": "*",
+ "day_of_month": "*",
+ "day_of_week": "*",
+ "month": "*",
+ "machine": "www103"
}
}
diff --git a/Tests/example_configurations/test.xml b/Tests/example_configurations/test.xml
index 5705baa..b7f3516 100755
--- a/Tests/example_configurations/test.xml
+++ b/Tests/example_configurations/test.xml
@@ -1,30 +1,43 @@
+
- s3_synchornize
- mwe:photo:s3 asgasg afasf
+ command1
+ ./some/command1
*/13
*
*
*
*
- ./logs/schema_validate.log
+ ./logs/some_log1.log
www*
+ this is some comment for this crontab
- k.kuczek@tvn.pl
+ test@test.pl
- s3_synchornize2
- mwe:photo:s3 asgasg afasf
+ command2
+ ./some/command2
*
*
*
*
*
- ./logs/schema_validate.log
+ ./logs/some_log2.log
www103
- j.zieba@tvn.pl
+ test@test.com
+ 1
+
+ command_without_log_file
+ ./some/command_without_log_file
+ *
+ *
+ *
+ *
+ *
+ www103
+
diff --git a/Tests/example_configurations/test.yaml b/Tests/example_configurations/test.yml
similarity index 71%
rename from Tests/example_configurations/test.yaml
rename to Tests/example_configurations/test.yml
index 03a4283..8d3edfe 100755
--- a/Tests/example_configurations/test.yaml
+++ b/Tests/example_configurations/test.yml
@@ -22,4 +22,12 @@ command2:
variables:
MAILTO: test@test.com
NO_VALIDATE: true
+command_without_log_file:
+ command: "./some/command_without_log_file"
+ minute: '*'
+ hour: '*'
+ day_of_month: '*'
+ day_of_week: '*'
+ month: '*'
+ machine: www103
diff --git a/Tests/features/echo.feature b/Tests/features/echo.feature
new file mode 100644
index 0000000..ee4b336
--- /dev/null
+++ b/Tests/features/echo.feature
@@ -0,0 +1,29 @@
+Feature: Echoing crontab
+ As a Developer
+ I want to echo crontab from app
+#
+# Scenario:
+# When I run echo command with ini type
+# Then The exit code should be 0
+# And The display should contain:
+# """
+#Your crontab will look like:
+##WARNING!!!
+##This crontab file it at least partially managed by Crontab by Hexmedia, please check all restrictions that comes with that library at: https://github.com/Hexmedia/Crontab/blob/master/README.md
+##EOT
+#
+#
+#
+## ------------ CURRENTLY MANAGED by Test --------------
+#
+##DO NOT MODIFY! This task is managed by Crontab library by Hexmedia 0cbc6611f5341b9a85da40865f5647c
+##
+#MAILTO=test@test.pl
+#*/13 * * * * ./some/command1 > ./logs/some_log1.log
+##DO NOT MODIFY! This task is managed by Crontab library by Hexmedia 0cbc6611f5f6034d349bc599edc77a3
+##
+#MAILTO=test@test.com
+#NO_VALIDATE=1
+#* * * * * ./some/command2 > ./logs/some_log2.log
+# """
+#
diff --git a/Tests/features/synchronzie.feature b/Tests/features/synchronzie.feature
new file mode 100644
index 0000000..a8e44e4
--- /dev/null
+++ b/Tests/features/synchronzie.feature
@@ -0,0 +1,233 @@
+Feature: Synchronization of crontab
+ As a Developer
+ I want to synchronize my cron with application configuration
+
+ Background:
+ Given The process builder is fake
+ And Crontab save will be called
+
+ Scenario Outline: Synchronizing with different types
+ Given "'crontab' '-l'" command will have 0 as exit code and will return:
+ """
+ */10 * * * * test
+
+ """
+ When I run synchronize command with file "./Tests/example_configurations/test." and options:
+ """
+ -t
+ """
+ Then The exit code should be 0
+ And The display should contain:
+ """
+ Your crontab has been updated!
+ """
+ And Crontab should be:
+ """
+ #WARNING!!!
+ #This crontab file it at least partially managed by Crontab by Hexmedia, please check all restrictions that comes with that library at: https://github.com/Hexmedia/Crontab/blob/master/README.md
+ #EOT
+
+
+ */10 * * * * test
+
+ # ------------ CURRENTLY MANAGED by Test --------------
+
+ #DO NOT MODIFY! This task is managed by Crontab library by Hexmedia 0cbc6611f5341b9a85da40865f5647c
+ #
+ MAILTO=test@test.pl
+ */13 * * * * ./some/command1 > ./logs/some_log1.log
+ #DO NOT MODIFY! This task is managed by Crontab library by Hexmedia 0cbc6611f5f6034d349bc599edc77a3
+ #
+ MAILTO=test@test.com
+ NO_VALIDATE=1
+ * * * * * ./some/command2 > ./logs/some_log2.log
+ #DO NOT MODIFY! This task is managed by Crontab library by Hexmedia 0cbc6611f563c3f5f02e473809fe5c1
+ #
+ * * * * * ./some/command_without_log_file
+
+ """
+
+ Examples:
+ | type | ext |
+ | ini | ini |
+ | yaml | yml |
+ | xml | xml |
+ | json | json |
+ | yml | yml |
+
+ Scenario Outline: Working without crontab
+ Given "'crontab' '-l'" command will have 0 as exit code and will return:
+ """
+ """
+ When I run synchronize command with file "./Tests/example_configurations/test." and options:
+ """
+ -t
+ """
+ Then The exit code should be 0
+ And The display should contain:
+ """
+ Your crontab has been updated!
+ """
+ And Crontab should be:
+ """
+ #WARNING!!!
+ #This crontab file it at least partially managed by Crontab by Hexmedia, please check all restrictions that comes with that library at: https://github.com/Hexmedia/Crontab/blob/master/README.md
+ #EOT
+
+
+
+ # ------------ CURRENTLY MANAGED by Test --------------
+
+ #DO NOT MODIFY! This task is managed by Crontab library by Hexmedia 0cbc6611f5341b9a85da40865f5647c
+ #
+ MAILTO=test@test.pl
+ */13 * * * * ./some/command1 > ./logs/some_log1.log
+ #DO NOT MODIFY! This task is managed by Crontab library by Hexmedia 0cbc6611f5f6034d349bc599edc77a3
+ #
+ MAILTO=test@test.com
+ NO_VALIDATE=1
+ * * * * * ./some/command2 > ./logs/some_log2.log
+ #DO NOT MODIFY! This task is managed by Crontab library by Hexmedia 0cbc6611f563c3f5f02e473809fe5c1
+ #
+ * * * * * ./some/command_without_log_file
+
+ """
+
+ Examples:
+ | type | ext |
+ | ini | ini |
+ | yaml | yml |
+ | xml | xml |
+ | json | json |
+ | yml | yml |
+
+ Scenario: It is not updating when there are no managed
+ Given "'crontab' '-l'" command will have 0 as exit code and will return:
+ """
+ */10 * * * * test
+
+ """
+ When I run synchronize command with file "./Tests/example_configurations/empty.xml" and options:
+ """
+ --type=xml
+ """
+ Then The exit code should be 0
+ And The display should contain:
+ """
+ Your crontab does not need to be updated!
+
+ """
+
+ @not_ready
+ Scenario: I run synchronize with unexisting file
+ Given "'crontab' '-l'" command will have 0 as exit code and will return:
+ """
+ */10 * * * * test
+
+ """
+ When I run synchronize command with file "./Tests/example_configurations/test.dne" and options:
+ """
+ --type=xml
+ """
+ Then The exit code should be 1
+ And The display should contain:
+ """
+ File "./Tests/example_configurations/test.dne" does not exists!
+ """
+
+ @test
+ Scenario Outline: I run synchronize with wrong type
+ Given "'crontab' '-l'" command will have 0 as exit code and will return:
+ """
+ */10 * * * * test
+
+ """
+ When I run synchronize command with file "./Tests/example_configurations/test." and options:
+ """
+ --type=
+ """
+ Then The exit code should be 1
+ And The display should contain:
+ """
+ ./Tests/example_configurations/test.' does not have --type= or has error in formatting.
+ """
+
+ Examples:
+ | type | ext |
+ | xml | yml |
+ | ini | xml |
+ | yml | json |
+ | json | ini |
+
+ @not_ready
+ Scenario Outline: I run synchronize without giving type
+ Given "'crontab' '-l'" command will have 0 as exit code and will return:
+ """
+ */10 * * * * test
+
+ """
+ When I run synchronize command with file "./Tests/example_configurations/test."
+ Then The exit code should be 0
+ And The display should contain:
+ """
+ Your crontab has been updated!
+ """
+ And Crontab should be:
+ """
+ #WARNING!!!
+ #This crontab file it at least partially managed by Crontab by Hexmedia, please check all restrictions that comes with that library at: https://github.com/Hexmedia/Crontab/blob/master/README.md
+ #EOT
+
+
+ */10 * * * * test
+
+ # ------------ CURRENTLY MANAGED by Test --------------
+
+ #DO NOT MODIFY! This task is managed by Crontab library by Hexmedia 0cbc6611f5341b9a85da40865f5647c
+ #
+ MAILTO=test@test.pl
+ */13 * * * * ./some/command1 > ./logs/some_log1.log
+ #DO NOT MODIFY! This task is managed by Crontab library by Hexmedia 0cbc6611f5f6034d349bc599edc77a3
+ #
+ MAILTO=test@test.com
+ NO_VALIDATE=1
+ * * * * * ./some/command2 > ./logs/some_log2.log
+ #DO NOT MODIFY! This task is managed by Crontab library by Hexmedia 0cbc6611f563c3f5f02e473809fe5c1
+ #
+ * * * * * ./some/command_without_log_file
+
+ """
+ Examples:
+ | ext |
+ | ini |
+ | yml |
+ | xml |
+ | json |
+ | yml |
+
+ @not_ready @desc_not_ready
+ Scenario: Dry run
+ Given "'crontab' '-l'" command will have 0 as exit code and will return:
+ """
+ */10 * * * * test
+
+ """
+ When I run synchronize command with file "./Tests/example_configurations/test." and options:
+ """
+ --dry-run
+ """
+ Then The exit code should be 0
+
+ @not_ready @desc_not_ready
+ Scenario: With username
+ Given "'crontab' '-l'" command will have 0 as exit code and will return:
+ """
+ */10 * * * * test
+
+ """
+ When I run synchronize command with file "./Tests/example_configurations/test." and options:
+ """
+ --user=kuczek
+ """
+ Then The exit code should be 0
+
diff --git a/Tests/spec/ApplicationSpec.php b/Tests/spec/ApplicationSpec.php
new file mode 100644
index 0000000..35c2ade
--- /dev/null
+++ b/Tests/spec/ApplicationSpec.php
@@ -0,0 +1,27 @@
+shouldHaveType('Hexmedia\Crontab\Application');
+ $this->shouldImplement('Symfony\Component\Console\Application');
+ }
+
+ function it_has_added_all_commands()
+ {
+ $this->all()->shouldHaveCount(5);
+ }
+}
diff --git a/Tests/spec/CrontabSpec.php b/Tests/spec/CrontabSpec.php
index adfe7a7..2c910d0 100755
--- a/Tests/spec/CrontabSpec.php
+++ b/Tests/spec/CrontabSpec.php
@@ -12,6 +12,13 @@
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
+/**
+ * Class CrontabSpec
+ *
+ * @package spec\Hexmedia\Crontab
+ *
+ * @covers Hexmedia\Crontab\Crontab
+ */
class CrontabSpec extends ObjectBehavior
{
public $name = "aaa";
diff --git a/Tests/spec/Parser/Ini/AustinHydeParserSpec.php b/Tests/spec/Parser/Ini/AustinHydeParserSpec.php
index 58cdd08..9954750 100644
--- a/Tests/spec/Parser/Ini/AustinHydeParserSpec.php
+++ b/Tests/spec/Parser/Ini/AustinHydeParserSpec.php
@@ -1,11 +1,21 @@
+ * @copyright 2013-2016 Hexmedia.pl
+ * @license @see LICENSE
+ */
namespace spec\Hexmedia\Crontab\Parser\Ini;
-use dev\Hexmedia\Crontab\PhpSpec\Parser\IniParserObjectBehavior;
+use dev\Hexmedia\Crontab\PhpSpec\Parser\AbstractIniParserObjectBehavior;
use Prophecy\Argument;
-class AustinHydeParserSpec extends IniParserObjectBehavior
+/**
+ * Class AustinHydeParserSpec
+ *
+ * @package spec\Hexmedia\Crontab\Parser\Ini
+ */
+class AustinHydeParserSpec extends AbstractIniParserObjectBehavior
{
function it_is_initializable()
{
diff --git a/Tests/spec/Parser/Ini/ParserFactorySpec.php b/Tests/spec/Parser/Ini/ParserFactorySpec.php
index 6cbe039..38fd68e 100644
--- a/Tests/spec/Parser/Ini/ParserFactorySpec.php
+++ b/Tests/spec/Parser/Ini/ParserFactorySpec.php
@@ -1,10 +1,20 @@
+ * @copyright 2013-2016 Hexmedia.pl
+ * @license @see LICENSE
+ */
namespace spec\Hexmedia\Crontab\Parser\Ini;
use dev\Hexmedia\Crontab\PhpSpec\Parser\FactoryObjectBehavior;
use Prophecy\Argument;
+/**
+ * Class ParserFactorySpec
+ *
+ * @package spec\Hexmedia\Crontab\Parser\Ini
+ */
class ParserFactorySpec extends FactoryObjectBehavior
{
protected function getType()
@@ -19,6 +29,10 @@ protected function getWorkingParser()
protected function getParsersCount()
{
+ if (defined("HHVM_VERSION")) {
+ return 1;
+ }
+
return 3;
}
}
diff --git a/Tests/spec/Parser/Ini/Zend2ParserSpec.php b/Tests/spec/Parser/Ini/Zend2ParserSpec.php
index 669843b..6f6e9d8 100644
--- a/Tests/spec/Parser/Ini/Zend2ParserSpec.php
+++ b/Tests/spec/Parser/Ini/Zend2ParserSpec.php
@@ -1,12 +1,31 @@
+ * @copyright 2013-2016 Hexmedia.pl
+ * @license @see LICENSE
+ */
namespace spec\Hexmedia\Crontab\Parser\Ini;
-use dev\Hexmedia\Crontab\PhpSpec\Parser\IniParserObjectBehavior;
+use dev\Hexmedia\Crontab\PhpSpec\Parser\AbstractIniParserObjectBehavior;
+use PhpSpec\Exception\Example\SkippingException;
use Prophecy\Argument;
-class Zend2ParserSpec extends IniParserObjectBehavior
+/**
+ * Class Zend2ParserSpec
+ *
+ * @package spec\Hexmedia\Crontab\Parser\Ini
+ */
+class Zend2ParserSpec extends AbstractIniParserObjectBehavior
{
+ function let() {
+ if (defined('HHVM_VERSION')) {
+ throw new SkippingException("Zend2 is not compatible with HHVM.");
+ }
+
+ parent::let();
+ }
+
function it_is_initializable()
{
$this->shouldHaveType('Hexmedia\Crontab\Parser\Ini\Zend2Parser');
diff --git a/Tests/spec/Parser/Ini/ZendParserSpec.php b/Tests/spec/Parser/Ini/ZendParserSpec.php
index feb9923..c241118 100644
--- a/Tests/spec/Parser/Ini/ZendParserSpec.php
+++ b/Tests/spec/Parser/Ini/ZendParserSpec.php
@@ -1,12 +1,31 @@
+ * @copyright 2013-2016 Hexmedia.pl
+ * @license @see LICENSE
+ */
namespace spec\Hexmedia\Crontab\Parser\Ini;
-use dev\Hexmedia\Crontab\PhpSpec\Parser\IniParserObjectBehavior;
+use dev\Hexmedia\Crontab\PhpSpec\Parser\AbstractIniParserObjectBehavior;
+use PhpSpec\Exception\Example\SkippingException;
use Prophecy\Argument;
-class ZendParserSpec extends IniParserObjectBehavior
+/**
+ * Class ZendParserSpec
+ *
+ * @package spec\Hexmedia\Crontab\Parser\Ini
+ */
+class ZendParserSpec extends AbstractIniParserObjectBehavior
{
+ function let() {
+ if (defined('HHVM_VERSION')) {
+ throw new SkippingException("Zend is not compatible with HHVM.");
+ }
+
+ parent::let();
+ }
+
function it_is_initializable()
{
$this->shouldHaveType('Hexmedia\Crontab\Parser\Ini\ZendParser');
diff --git a/Tests/spec/Parser/Json/ParserFactorySpec.php b/Tests/spec/Parser/Json/ParserFactorySpec.php
new file mode 100644
index 0000000..b24c577
--- /dev/null
+++ b/Tests/spec/Parser/Json/ParserFactorySpec.php
@@ -0,0 +1,24 @@
+shouldHaveType('Hexmedia\Crontab\Parser\Json\PhpParser');
+ }
+}
diff --git a/Tests/spec/Parser/Unix/ParserFactorySpec.php b/Tests/spec/Parser/Unix/ParserFactorySpec.php
index 98d5870..971f211 100644
--- a/Tests/spec/Parser/Unix/ParserFactorySpec.php
+++ b/Tests/spec/Parser/Unix/ParserFactorySpec.php
@@ -37,7 +37,7 @@ function it_returns_correct_praser()
{
$this->isSystemSupported();
- $this->create('')->shouldImplement('Hexmedia\Crontab\Parser\ParserInterface');
+ $this->create('', '/tmp/file')->shouldImplement('Hexmedia\Crontab\Parser\ParserInterface');
}
function it_is_constructing_with_prefered_full_name()
@@ -45,7 +45,7 @@ function it_is_constructing_with_prefered_full_name()
$this->isSystemSupported();
$this->beConstructedWith($this->getFullWorkingParserName());
- $this->create("[some]")->shouldHaveType($this->getFullWorkingParserName());
+ $this->create('[some]', '/tmp/file')->shouldHaveType($this->getFullWorkingParserName());
}
function it_is_constructing_with_prefered_only_class_name()
@@ -53,7 +53,7 @@ function it_is_constructing_with_prefered_only_class_name()
$this->isSystemSupported();
$this->beConstructedWith($this->getWorkingParser());
- $this->create("[some]")->shouldHaveType($this->getFullWorkingParserName());
+ $this->create('[some]', '/tmp/file')->shouldHaveType($this->getFullWorkingParserName());
}
}
diff --git a/Tests/spec/Parser/Unix/UnixParserSpec.php b/Tests/spec/Parser/Unix/UnixParserSpec.php
index 5f8eecb..a637397 100644
--- a/Tests/spec/Parser/Unix/UnixParserSpec.php
+++ b/Tests/spec/Parser/Unix/UnixParserSpec.php
@@ -21,7 +21,7 @@ function let()
$content = file_get_contents($file);
- $this->beConstructedWith($content);
+ $this->beConstructedWith($content, null);
}
function it_is_not_working_with_wrong_file()
@@ -30,7 +30,7 @@ function it_is_not_working_with_wrong_file()
$content = file_get_contents($file);
- $this->beConstructedWith($content);
+ $this->beConstructedWith($content, null);
$this->shouldThrow(new ParseException('Cannot match this file error: \'wrong file format\''))->duringParse();
}
@@ -97,4 +97,11 @@ function it_is_loading_file_correctly()
$parsed[$i]['comment']->shouldReturn($comments[$i]);
}
}
+
+ function it_is_returning_null_when_there_is_no_system_crontab()
+ {
+ $this->beConstructedWith(false, null);
+
+ $this->parse()->shouldReturn(null);
+ }
}
diff --git a/Tests/spec/Parser/Xml/ParserFactorySpec.php b/Tests/spec/Parser/Xml/ParserFactorySpec.php
new file mode 100644
index 0000000..49d0ef3
--- /dev/null
+++ b/Tests/spec/Parser/Xml/ParserFactorySpec.php
@@ -0,0 +1,24 @@
+shouldHaveType('Hexmedia\Crontab\Parser\Xml\PhpParser');
+ }
+}
diff --git a/Tests/spec/Parser/Yaml/ParserFactorySpec.php b/Tests/spec/Parser/Yaml/ParserFactorySpec.php
index 62403d6..898f1d1 100644
--- a/Tests/spec/Parser/Yaml/ParserFactorySpec.php
+++ b/Tests/spec/Parser/Yaml/ParserFactorySpec.php
@@ -24,6 +24,10 @@ protected function getWorkingParser()
protected function getParsersCount()
{
+ if (defined("HHVM_VERSION")) {
+ return 1;
+ }
+
return 2;
}
}
diff --git a/Tests/spec/Parser/Yaml/SymfonyParserSpec.php b/Tests/spec/Parser/Yaml/SymfonyParserSpec.php
index 5567651..67e321c 100644
--- a/Tests/spec/Parser/Yaml/SymfonyParserSpec.php
+++ b/Tests/spec/Parser/Yaml/SymfonyParserSpec.php
@@ -2,10 +2,10 @@
namespace spec\Hexmedia\Crontab\Parser\Yaml;
-use dev\Hexmedia\Crontab\PhpSpec\Parser\YamlParserObjectBehavior;
+use dev\Hexmedia\Crontab\PhpSpec\Parser\AbstractYamlParserObjectBehavior;
use Prophecy\Argument;
-class SymfonyParserSpec extends YamlParserObjectBehavior
+class SymfonyParserSpec extends AbstractYamlParserObjectBehavior
{
}
diff --git a/Tests/spec/Parser/Yaml/ZendParserSpec.php b/Tests/spec/Parser/Yaml/ZendParserSpec.php
index 33d8fde..cd4bcd6 100644
--- a/Tests/spec/Parser/Yaml/ZendParserSpec.php
+++ b/Tests/spec/Parser/Yaml/ZendParserSpec.php
@@ -2,10 +2,17 @@
namespace spec\Hexmedia\Crontab\Parser\Yaml;
-use dev\Hexmedia\Crontab\PhpSpec\Parser\YamlParserObjectBehavior;
+use dev\Hexmedia\Crontab\PhpSpec\Parser\AbstractYamlParserObjectBehavior;
+use PhpSpec\Exception\Example\SkippingException;
use Prophecy\Argument;
-class ZendParserSpec extends YamlParserObjectBehavior
+class ZendParserSpec extends AbstractYamlParserObjectBehavior
{
+ function let() {
+ if (defined('HHVM_VERSION')) {
+ throw new SkippingException("Zend is not compatible with HHVM.");
+ }
+ parent::let();
+ }
}
diff --git a/Tests/spec/Reader/SystemReaderSpec.php b/Tests/spec/Reader/SystemReaderSpec.php
index 4b32f11..f176fd5 100644
--- a/Tests/spec/Reader/SystemReaderSpec.php
+++ b/Tests/spec/Reader/SystemReaderSpec.php
@@ -11,11 +11,18 @@
use Hexmedia\Crontab\Exception\ClassNotExistsException;
use Prophecy\Argument;
+/**
+ * Class SystemReaderSpec
+ *
+ * @package spec\Hexmedia\Crontab\Reader
+ *
+ * @covers Hexmedia\Crontab\Reader\SystemReader
+ */
class SystemReaderSpec extends SystemAwareObjectBehavior
{
function let()
{
- $this->beConstructedWith("kuczek", null);
+ $this->beConstructedWith(null, null);
}
function it_is_initializable()
diff --git a/Tests/spec/Reader/UnixFileReaderSpec.php b/Tests/spec/Reader/UnixFileReaderSpec.php
index 6546e64..0073c84 100644
--- a/Tests/spec/Reader/UnixFileReaderSpec.php
+++ b/Tests/spec/Reader/UnixFileReaderSpec.php
@@ -7,14 +7,15 @@
namespace spec\Hexmedia\Crontab\Reader;
-use PhpSpec\ObjectBehavior;
+use dev\Hexmedia\Crontab\PhpSpec\SystemAwareObjectBehavior;
use Prophecy\Argument;
-class UnixFileReaderSpec extends ObjectBehavior
+class UnixFileReaderSpec extends SystemAwareObjectBehavior
{
function let()
{
- $this->beConstructedWith("./Test/example_configurations/test.unix");
+ $this->isSystemSupported();
+ $this->beConstructedWith("./Tests/example_configurations/test.unix");
}
function it_is_initializable()
diff --git a/Tests/spec/Reader/UnixSystemReaderSpec.php b/Tests/spec/Reader/UnixSystemReaderSpec.php
index 40c2db8..aa01f10 100644
--- a/Tests/spec/Reader/UnixSystemReaderSpec.php
+++ b/Tests/spec/Reader/UnixSystemReaderSpec.php
@@ -7,7 +7,7 @@
namespace spec\Hexmedia\Crontab\Reader;
-use PhpSpec\ObjectBehavior;
+use dev\Hexmedia\Crontab\PhpSpec\SystemAwareObjectBehavior;
use Prophecy\Argument;
/**
@@ -20,11 +20,12 @@
* @method static $this removeSupportedOs(string $name)
* @method static array getSupportedOses()
*/
-class UnixSystemReaderSpec extends ObjectBehavior
+class UnixSystemReaderSpec extends SystemAwareObjectBehavior
{
function let()
{
- $this->beConstructedWith("kuczek", null);
+ $this->isSystemSupported();
+ $this->beConstructedWith(null, null);
}
function it_is_initializable()
diff --git a/Tests/spec/Reader/YamlReaderSpec.php b/Tests/spec/Reader/YamlReaderSpec.php
index 048abf2..353a1d5 100644
--- a/Tests/spec/Reader/YamlReaderSpec.php
+++ b/Tests/spec/Reader/YamlReaderSpec.php
@@ -15,7 +15,7 @@ class YamlReaderSpec extends ObjectBehavior
{
function let(Crontab $crontab)
{
- $file = "./Tests/example_configurations/test.yaml";
+ $file = "./Tests/example_configurations/test.yml";
$machine = "www101";
$this->beConstructedWith($file, $crontab, $machine);
}
diff --git a/Tests/spec/ReaderFactorySpec.php b/Tests/spec/ReaderFactorySpec.php
index 55e6970..5a97f0f 100644
--- a/Tests/spec/ReaderFactorySpec.php
+++ b/Tests/spec/ReaderFactorySpec.php
@@ -10,6 +10,13 @@
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
+/**
+ * Class ReaderFactorySpec
+ *
+ * @package spec\Hexmedia\Crontab
+ *
+ * @covers Hexmedia\Crontab\ReaderFactory
+ */
class ReaderFactorySpec extends ObjectBehavior
{
function it_is_initializable()
diff --git a/Tests/spec/System/UnixSpec.php b/Tests/spec/System/UnixSpec.php
index 2d89698..63d4239 100644
--- a/Tests/spec/System/UnixSpec.php
+++ b/Tests/spec/System/UnixSpec.php
@@ -33,11 +33,21 @@ function let(ProcessBuilder $processBuilder, Process $process)
$this::setProcessBuilder($processBuilder);
}
+ function letGo()
+ {
+ $this::setProcessBuilder(null);
+ }
+
function it_is_initializable()
{
$this->shouldHaveType('Hexmedia\Crontab\System\Unix');
}
+ function it_has_default_porcess_builder()
+ {
+ $this::getProcessBuilder()->shouldHaveType('Symfony\Component\Process\ProcessBuilder');
+ }
+
function it_does_not_allow_to_add_second_time()
{
$this::addUnix("Foo")->shouldReturn(true);
diff --git a/Tests/spec/TaskSpec.php b/Tests/spec/TaskSpec.php
index 78ead9c..459fb55 100644
--- a/Tests/spec/TaskSpec.php
+++ b/Tests/spec/TaskSpec.php
@@ -11,6 +11,13 @@
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
+/**
+ * Class TaskSpec
+ *
+ * @package spec\Hexmedia\Crontab
+ *
+ * @covers Hexmedia\Reader\Task
+ */
class TaskSpec extends ObjectBehavior
{
function it_is_initializable()
diff --git a/Tests/spec/VariablesSpec.php b/Tests/spec/VariablesSpec.php
index fde3f07..900d0a4 100644
--- a/Tests/spec/VariablesSpec.php
+++ b/Tests/spec/VariablesSpec.php
@@ -11,6 +11,13 @@
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
+/**
+ * Class VariablesSpec
+ *
+ * @package spec\Hexmedia\Crontab
+ *
+ * @covers Hexmedia\Variables
+ */
class VariablesSpec extends ObjectBehavior
{
function let()
diff --git a/Tests/spec/Writer/System/UnixWriterSpec.php b/Tests/spec/Writer/System/UnixWriterSpec.php
index af702b2..b430109 100644
--- a/Tests/spec/Writer/System/UnixWriterSpec.php
+++ b/Tests/spec/Writer/System/UnixWriterSpec.php
@@ -7,15 +7,44 @@
namespace spec\Hexmedia\Crontab\Writer\System;
+use dev\Hexmedia\Crontab\PhpSpec\SystemAwareObjectBehavior;
use Hexmedia\Crontab\Crontab;
+use Hexmedia\Crontab\System\Unix;
use Hexmedia\Crontab\Task;
use Hexmedia\Crontab\Variables;
-use PhpSpec\ObjectBehavior;
+use Hexmedia\Symfony\FakeProcess\FakeProcessBuilder;
+use PhpSpec\Exception\Example\FailureException;
use Prophecy\Argument;
-class UnixWriterSpec extends ObjectBehavior
+class UnixWriterSpec extends SystemAwareObjectBehavior
{
- private function prepareTask(&$task, $variables, $notManaged = false)
+ private $defaultContent = << some_log_file.log
+#This is some comment with
+#two lines
+*/10 * * * * test > some_log_file.log
+
+# ------------ CURRENTLY MANAGED by TestAopTest --------------
+
+#DO NOT MODIFY! This task is managed by Crontab library by Hexmedia bb83a7fd849c0ab6ec0cfb38d3db6a2
+#This is some comment with
+#two lines
+*/10 * * * * test > some_log_file.log
+#DO NOT MODIFY! This task is managed by Crontab library by Hexmedia bb83a7fd849c0ab6ec0cfb38d3db6a2
+#This is some comment with
+#two lines
+*/10 * * * * test > some_log_file.log
+
+CONTENT;
+
+ private function prepareTask(&$task, $variables, $notManaged = false, $comment = true)
{
$task->getCommand()->willReturn("test");
$task->getMonth()->willReturn("*");
@@ -24,7 +53,7 @@ private function prepareTask(&$task, $variables, $notManaged = false)
$task->getHour()->willReturn("*");
$task->getMinute()->willReturn("*/10");
$task->getLogFile()->willReturn("some_log_file.log");
- $task->getBeforeComment()->willReturn("This is some comment with \n two lines");
+ $task->getBeforeComment()->willReturn($comment ? "This is some comment with \ntwo lines" : '');
$task->isNotManaged()->willReturn($notManaged);
$task->getVariables()->willReturn($variables);
$task->getName()->willReturn("synchronize1");
@@ -32,6 +61,8 @@ private function prepareTask(&$task, $variables, $notManaged = false)
function let(Crontab $crontab, Task $nmTask1, Task $nmTask2, Task $task1, Task $task2, Variables $variables1)
{
+ $this->isSystemSupported();
+
$this->prepareTask($task1, $variables1);
$this->prepareTask($task2, $variables1);
@@ -50,41 +81,11 @@ function it_is_initializable()
$this->shouldImplement('Hexmedia\Crontab\Writer\System\WriterInterface');
}
-// function it_is_able_to_write($crontab)
-// {
-// $this->write($crontab)->shouldReturn(true);
-// }
-//
function it_is_able_to_get_content($crontab)
{
- $shouldBe = << some_log_file.log
-#This is some comment with
-# two lines
-*/10 * * * * test > some_log_file.log
-
-# ------------ CURRENTLY MANAGED by TestAopTest --------------
-
-#DO NOT MODIFY! This task is managed by Crontab library by Hexmedia bb83a7fd849c0ab6ec0cfb38d3db6a2
-#This is some comment with
-# two lines
-*/10 * * * * test > some_log_file.log
-#DO NOT MODIFY! This task is managed by Crontab library by Hexmedia bb83a7fd849c0ab6ec0cfb38d3db6a2
-#This is some comment with
-# two lines
-*/10 * * * * test > some_log_file.log
-
-CONTENT;
$this
->getContent($crontab)
- ->shouldReturn($shouldBe);
+ ->shouldReturn($this->defaultContent);
}
function it_has_support_for_variables(Task $task3, Variables $variables3, Crontab $crontab2)
@@ -94,7 +95,7 @@ function it_has_support_for_variables(Task $task3, Variables $variables3, Cronta
$variables3->current()->willReturn('value');
$variables3->key()->willReturn('key');
$variables3->rewind()->shouldBeCalled();
- $variables3->valid()->willReturn(true,false);
+ $variables3->valid()->willReturn(true, false);
$variables3->next()->shouldBeCalled();
$crontab2->getName()->willReturn("TestAopTest");
@@ -107,7 +108,7 @@ function it_has_support_for_variables(Task $task3, Variables $variables3, Cronta
->shouldReturn(
<< some_log_file.log
CONTENT
);
}
+
+ function it_works_with_crons_without_comments(Task $taskWC, Variables $variablesWC, Crontab $crontabWC)
+ {
+ $this->prepareTask($taskWC, $variablesWC, true, false);
+
+ $variablesWC->current()->willReturn('value');
+ $variablesWC->key()->willReturn('key');
+ $variablesWC->rewind()->shouldBeCalled();
+ $variablesWC->valid()->willReturn(true, false);
+ $variablesWC->next()->shouldBeCalled();
+
+ $crontabWC->getName()->willReturn("TestAopTest");
+
+ $crontabWC->getManagedTasks()->willReturn(array($taskWC));
+ $crontabWC->getNotManagedTasks()->willReturn(array());
+
+// echo($this->getContent($crontabWC)->getWrappedObject());
+// die();
+
+ $this
+ ->getContent($crontabWC)
+ ->shouldReturn(
+ << some_log_file.log
+
+CONTENT
+ );
+ }
+
+ function it_allows_to_write($crontab)
+ {
+ $processBuilder = new FakeProcessBuilder();
+
+ $shouldBe = $this->defaultContent;
+
+ $processBuilder->addCommand(
+ "'crontab' '(/var)?/tmp/.*'",
+ function ($command) use ($shouldBe) {
+ if (preg_match("#'crontab' '((/var)?/tmp/.*)'#", $command, $matches)) {
+ $content = file_get_contents($matches[1]);
+
+ if ($content !== $shouldBe) {
+ throw new FailureException("Content in not correct");
+ }
+ }
+ },
+ 1
+ );
+
+ Unix::setProcessBuilder($processBuilder);
+
+ $this->write($crontab)->shouldReturn(true);
+
+ Unix::setProcessBuilder(null);
+ }
}
diff --git a/behat.yml b/behat.yml
new file mode 100644
index 0000000..891f938
--- /dev/null
+++ b/behat.yml
@@ -0,0 +1,38 @@
+default:
+ autoload:
+ '': %paths.base%/Tests/features/bootstrap
+ suites:
+ default:
+ contexts: [ 'dev\Hexmedia\Crontab\Behat\ApplicationContext' ]
+ paths: [ %paths.base%/Tests/features ]
+ formatters:
+ pretty: true
+ filters:
+ tags: ~@not_ready
+ all:
+ contexts: [ 'dev\Hexmedia\Crontab\Behat\ApplicationContext' ]
+ paths: [ %paths.base%/Tests/features ]
+ formatters:
+ pretty: true
+
+ travis:
+ contexts: [ 'dev\Hexmedia\Crontab\Behat\ApplicationContext' ]
+ paths: [ %paths.base%/Tests/features_travis ]
+ formatters:
+ pretty: true
+ filters:
+ tags: ~@not_ready
+
+ formatters:
+ html:
+ output_path: %paths.base%/build/report/behat
+ pretty: ~
+
+ extensions:
+ emuse\BehatHTMLFormatter\BehatHTMLFormatterExtension:
+ name: html
+ renderer: Twig
+ file_name: index
+ print_args: true
+ print_outp: true
+ loop_break: true
diff --git a/bin/crontab b/bin/crontab
index 720df60..7390e5f 100755
--- a/bin/crontab
+++ b/bin/crontab
@@ -1,13 +1,8 @@
#!/usr/bin/env php
-
add(new \Hexmedia\Crontab\Console\SynchronizeCommand());
-$application->add(new \Hexmedia\Crontab\Console\EchoCommand());
-$application->add(new \Hexmedia\Crontab\Console\ClearCommand());
+$application = new \Hexmedia\Crontab\Application();
$application->run();
diff --git a/build.xml b/build.xml
index ff446ee..d722074 100644
--- a/build.xml
+++ b/build.xml
@@ -13,6 +13,7 @@
+
@@ -69,17 +70,17 @@
-
+
-
+
-
+
@@ -95,6 +96,7 @@
+
@@ -151,6 +153,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -345,7 +371,7 @@
-
+
@@ -353,9 +379,9 @@
-
-
+
+
-
+
diff --git a/composer.json b/composer.json
index fddfe66..5fc8297 100644
--- a/composer.json
+++ b/composer.json
@@ -53,7 +53,10 @@
"seld/jsonlint": "^1.4",
"hexmedia/yaml-linter": ">0.1,<2",
"austinhyde/iniparser": "~1.0@dev",
- "hexmedia/code-style": "~1.0@dev"
+ "hexmedia/code-style": "~1.0@dev",
+ "behat/behat": "~3.0",
+ "kuczek/behat-html-formatter": ">=0.1.2,<0.2",
+ "hexmedia/symfony-fake-process": ">2.0@dev,<4.0@dev"
},
"suggest": {
"symfony/yaml": "Enables support for yaml configuration files.",
diff --git a/doc/tasks.xsd b/doc/tasks.xsd
new file mode 100644
index 0000000..939bd1b
--- /dev/null
+++ b/doc/tasks.xsd
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src-dev/Behat/ApplicationContext.php b/src-dev/Behat/ApplicationContext.php
new file mode 100644
index 0000000..0437e6b
--- /dev/null
+++ b/src-dev/Behat/ApplicationContext.php
@@ -0,0 +1,276 @@
+
+ * @copyright 2013-2016 Hexmedia.pl
+ * @license @see LICENSE
+ */
+
+namespace dev\Hexmedia\Crontab\Behat;
+
+use Behat\Behat\Context\Context;
+use Behat\Behat\Context\SnippetAcceptingContext;
+use Behat\Gherkin\Node\PyStringNode;
+use Hexmedia\Crontab\Application;
+use Hexmedia\Crontab\System\Unix;
+use Hexmedia\Symfony\FakeProcess\FakeProcessBuilder;
+use PhpSpec\Matcher\MatchersProviderInterface;
+use Symfony\Component\Console\Tester\ApplicationTester;
+use PHPUnit_Framework_Assert as Assertions;
+
+/**
+ * Class CommandFeatureContext
+ *
+ * @package dev\Hexmedia\Crontab\Behat
+ */
+class ApplicationContext implements Context, MatchersProviderInterface, SnippetAcceptingContext
+{
+
+ /**
+ * @var ApplicationTester
+ */
+ private $tester;
+
+ /**
+ * @var Application
+ */
+ private $application;
+
+ /**
+ * @var int
+ */
+ private $lastExitCode;
+
+ /**
+ * @var string
+ */
+ private $lastDisplay;
+
+ /**
+ * @var FakeProcessBuilder
+ */
+ private $processBuilder;
+
+ /**
+ * @var string
+ */
+ private $currentCrontab;
+
+ /**
+ * @return array
+ */
+ public function getMatchers()
+ {
+ return array();
+ }
+
+ /**
+ * @beforeScenario
+ */
+ public function initApplication()
+ {
+ $this->application = new Application();
+
+ $this->application->setAutoExit(false);
+
+ $this->tester = new ApplicationTester($this->application);
+ }
+
+ /**
+ * @param string $command
+ * @param string $file
+ * @param PyStringNode $options
+ *
+ * @When /^I run (?P[a-zA-Z0-9\.\:]*) command with file \"(?P[^\"]*)\"$/
+ * @When /^I run (?P[a-zA-Z0-9\.\:]*) command with file \"(?P[^\"]*)\" and options:$/
+ */
+ public function iRunCommand($command, $file = null, PyStringNode $options = null)
+ {
+ $arguments = array(
+ 'command' => $command,
+ 'name' => 'Test',
+ );
+
+ $arguments['configuration-file'] = __DIR__ . "/../../" . $file;
+
+ $options = $this->parseOptions($options);
+
+ $arguments += $options;
+
+ $runOptions = array('interactive' => false, 'decorated' => false);
+
+ $this->lastExitCode = $this->tester->run($arguments, $runOptions);
+ $this->lastDisplay = $this->tester->getDisplay();
+ }
+
+ /**
+ * @param int $response
+ *
+ * @throws \Exception
+ *
+ * @Then /The exit code should be (\d+)/
+ *
+ * @SuppressWarnings(PHPMD.StaticAccess)
+ */
+ public function theExitCodeShouldBe($response)
+ {
+ if ((int) $response !== $this->lastExitCode) {
+ throw new \Exception($this->lastDisplay);
+ }
+
+ Assertions::assertSame((int) $response, $this->lastExitCode);
+ }
+
+ /**
+ * @param PyStringNode $content
+ *
+ * @Then Crontab should contain:
+ *
+ * @SuppressWarnings(PHPMD.StaticAccess)
+ */
+ public function crontabShouldContain(PyStringNode $content)
+ {
+ $crontab = $this->currentCrontab;
+
+ Assertions::assertNotFalse($crontab);
+
+ if ("" == $content->getRaw()) {
+ Assertions::assertEquals("", $crontab);
+ } else {
+ Assertions::assertContains($content->getRaw(), $crontab);
+ }
+ }
+
+ /**
+ * @param PyStringNode $content
+ *
+ * @Then Crontab should be:
+ *
+ * @SuppressWarnings(PHPMD.StaticAccess)
+ */
+ public function crontabShouldBe(PyStringNode $content)
+ {
+ $crontab = $this->currentCrontab;
+
+ Assertions::assertNotFalse($crontab);
+
+ if ("" == $content->getRaw()) {
+ Assertions::assertEquals("", $crontab);
+ } else {
+ Assertions::assertEquals($content->getRaw(), $crontab);
+ }
+ }
+
+ /**
+ * @param PyStringNode $display
+ *
+ * @Then The display should be:
+ *
+ * @SuppressWarnings(PHPMD.StaticAccess)
+ */
+ public function theDisplayShouldBe(PyStringNode $display)
+ {
+ Assertions::assertSame($display->getRaw(), $this->lastDisplay);
+ }
+
+ /**
+ * @param PyStringNode $display
+ *
+ * @Then The display should contain:
+ *
+ * @SuppressWarnings(PHPMD.StaticAccess)
+ */
+ public function theDisplayShouldContain(PyStringNode $display)
+ {
+ Assertions::assertContains($display->getRaw(), $this->lastDisplay);
+ }
+
+ /**
+ * @Then The display should be empty
+ *
+ * @SuppressWarnings(PHPMD.StaticAccess)
+ */
+ public function theDisplayShouldBeEmpty()
+ {
+ Assertions::assertEquals('', $this->lastDisplay);
+ }
+
+ /**
+ * @Given The process builder is fake
+ *
+ * @SuppressWarnings(PHPMD.StaticAccess)
+ */
+ public function theProcessBuilderIsFake()
+ {
+ $this->processBuilder = new FakeProcessBuilder();
+
+ Unix::setProcessBuilder($this->processBuilder);
+ }
+
+ /**
+ * @Given /^\"(?P[^\"]*)\" command will have (?P\d+) as exit code$/
+ * @Given /^\"(?P[^\"]*)\" command will have (?P\d+) as exit code and will return:/
+ *
+ * @param string $command
+ * @param string $code
+ * @param PyStringNode $string
+ */
+ public function commandWillHaveAsExitCodeAndWillReturn($command, $code, PyStringNode $string = null)
+ {
+ $this->processBuilder->addCommand(
+ $command,
+ function ($command) use ($string) {
+ if (null !== $string) {
+ return $string->getRaw();
+ }
+
+ return '';
+ },
+ $code
+ );
+ }
+
+ /**
+ * @Given Crontab save will be called
+ */
+ public function crontabSaveShouldBeCalled()
+ {
+ $command = "'crontab' '/tmp/.*'";
+
+ $content = '';
+ $this->currentCrontab = &$content;
+ $content = '1';
+
+ $this->processBuilder->addCommand(
+ $command,
+ function ($command) use (&$content) {
+ if (preg_match("#'crontab' '(/tmp/.*)'#", $command, $matches)) {
+ $content = file_get_contents($matches[1]);
+ }
+ },
+ 0
+ );
+ }
+
+ /**
+ * @param PyStringNode $options
+ *
+ * @return array
+ */
+ private function parseOptions(PyStringNode $options)
+ {
+ $return = array();
+
+ foreach ($options->getStrings() as $option) {
+ if (preg_match('/(?P