Refactored project structure.

This commit is contained in:
Dmitry Khomutov 2018-03-04 18:04:15 +07:00
commit c015d8c58b
No known key found for this signature in database
GPG key ID: EC19426474B37AAC
308 changed files with 39 additions and 47 deletions

View file

@ -0,0 +1,65 @@
<?php
namespace Tests\PHPCensor\Command;
use PHPCensor\Command\CreateAdminCommand;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
class CreateAdminCommandTest extends \PHPUnit\Framework\TestCase
{
/**
* @var \PHPCensor\Command\CreateAdminCommand|\PHPUnit_Framework_MockObject_MockObject
*/
protected $command;
/**
* @var \Symfony\Component\Console\Application|\PHPUnit_Framework_MockObject_MockObject
*/
protected $application;
/**
* @var \Symfony\Component\Console\Helper\QuestionHelper|\PHPUnit_Framework_MockObject_MockObject
*/
protected $helper;
public function setUp()
{
parent::setUp();
$userStoreMock = $this->getMockBuilder('PHPCensor\\Store\\UserStore')->getMock();
$this->command = new CreateAdminCommand($userStoreMock);
$this->helper = $this
->getMockBuilder('Symfony\\Component\\Console\\Helper\\QuestionHelper')
->setMethods(['ask'])
->getMock();
$this->application = new Application();
}
/**
* @return CommandTester
*/
protected function getCommandTester()
{
$this->application->getHelperSet()->set($this->helper, 'question');
$this->application->add($this->command);
$commandTester = new CommandTester($this->command);
return $commandTester;
}
public function testExecute()
{
$this->helper->expects($this->at(0))->method('ask')->will($this->returnValue('test@example.com'));
$this->helper->expects($this->at(1))->method('ask')->will($this->returnValue('A name'));
$this->helper->expects($this->at(2))->method('ask')->will($this->returnValue('foobar123'));
$commandTester = $this->getCommandTester();
$commandTester->execute([]);
self::assertEquals('User account created!' . PHP_EOL, $commandTester->getDisplay());
}
}

View file

@ -0,0 +1,78 @@
<?php
namespace Tests\PHPCensor\Command;
use PHPCensor\Command\CreateBuildCommand;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
class CreateBuildCommandTest extends \PHPUnit\Framework\TestCase
{
/**
* @var \PHPCensor\Command\CreateAdminCommand|\PHPUnit_Framework_MockObject_MockObject
*/
protected $command;
/**
* @var \Symfony\Component\Console\Application|\PHPUnit_Framework_MockObject_MockObject
*/
protected $application;
public function setUp()
{
parent::setUp();
$projectMock = $this->getMockBuilder('PHPCensor\\Model\\Project')->getMock();
$projectStoreMock = $this->getMockBuilder('PHPCensor\\Store\\ProjectStore')
->getMock();
$projectStoreMock->method('getById')
->will($this->returnValueMap([
[1, 'read', $projectMock],
[2, 'read', null],
]));
$buildServiceMock = $this->getMockBuilder('PHPCensor\\Service\\BuildService')
->disableOriginalConstructor()
->getMock();
$buildServiceMock->method('createBuild')
->withConsecutive(
[$projectMock, null, null, null, null, null],
[$projectMock, '92c8c6e', null, null, null, null],
[$projectMock, null, 'master', null, null, null]
);
$this->command = new CreateBuildCommand($projectStoreMock, $buildServiceMock);
$this->application = new Application();
}
protected function getCommandTester()
{
$this->application->add($this->command);
$command = $this->application->find('php-censor:create-build');
$commandTester = new CommandTester($command);
return $commandTester;
}
public function testExecute()
{
$commandTester = $this->getCommandTester();
$commandTester->execute(['projectId' => 1]);
$commandTester->execute(['projectId' => 1, '--commit' => '92c8c6e']);
$commandTester->execute(['projectId' => 1, '--branch' => 'master']);
}
/**
* @expectedException \InvalidArgumentException
*/
public function testExecuteWithUnknownProjectId()
{
$commandTester = $this->getCommandTester();
$commandTester->execute(['projectId' => 2]);
}
}

View file

@ -0,0 +1,277 @@
<?php
namespace Tests\PHPCensor\Command;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\Console\Helper\HelperSet;
class InstallCommandTest extends \PHPUnit\Framework\TestCase
{
public $config;
public $admin;
/**
* @var Application
*/
protected $application;
public function setUp()
{
parent::setUp();
$this->application = new Application();
$this->application->setHelperSet(new HelperSet());
}
/**
* @return \PHPUnit_Framework_MockObject_MockObject
*/
protected function getHelperMock()
{
// We check that there's no interaction with user.
return $this
->getMockBuilder('Symfony\\Component\\Console\\Helper\\QuestionHelper')
->setMethods(['ask'])
->getMock();
}
/**
* @return \PHPUnit_Framework_MockObject_MockObject
*/
protected function getInstallCommandMock()
{
// Current command, we need to mock all method that interact with
// Database & File system.
$command = $this->getMockBuilder('PHPCensor\\Command\\InstallCommand')
->setMethods([
'reloadConfig',
'verifyNotInstalled',
'verifyDatabaseDetails',
'setupDatabase',
'createAdminUser',
'createDefaultGroup',
'writeConfigFile',
'checkRequirements',
])->getMock();
$self = $this;
$command->expects($this->once())->method('verifyNotInstalled')->willReturn(true);
$command->expects($this->once())->method('verifyDatabaseDetails')->willReturn(true);
$command->expects($this->once())->method('setupDatabase')->willReturn(true);
$command->expects($this->once())->method('createAdminUser')->will(
$this->returnCallback(function ($adm) use ($self) {
$self->admin = $adm;
})
);
$command->expects($this->once())->method('writeConfigFile')->will(
$this->returnCallback(function ($cfg) use ($self) {
$self->config = $cfg;
})
);
$command->expects($this->once())->method('checkRequirements');
$command->expects($this->once())->method('createDefaultGroup');
return $command;
}
protected function getCommandTester($helper)
{
$this->application->getHelperSet()->set($helper, 'question');
$this->application->add($this->getInstallCommandMock());
$command = $this->application->find('php-censor:install');
$commandTester = new CommandTester($command);
return $commandTester;
}
protected function getConfig($exclude = null)
{
$config = [
'--db-host' => 'localhost',
'--db-port' => '3306',
'--db-name' => 'php-censor-db',
'--db-user' => 'php-censor-user',
'--db-password' => 'php-censor-password',
'--db-type' => 'mysql',
'--admin-email' => 'admin@php-censor.local',
'--admin-name' => 'admin',
'--admin-password' => 'admin-password',
'--url' => 'http://php-censor.local',
'--queue-use' => false,
];
if (!is_null($exclude)) {
unset($config[$exclude]);
}
return $config;
}
protected function executeWithoutParam($param = null, $dialog)
{
// Clean result variables.
$this->admin = [];
$this->config = [];
// Get tester and execute with extracted parameters.
$commandTester = $this->getCommandTester($dialog);
$parameters = $this->getConfig($param);
$commandTester->execute($parameters);
}
public function testAutomaticInstallation()
{
$dialog = $this->getHelperMock();
$dialog->expects($this->never())->method('ask');
$this->executeWithoutParam(null, $dialog);
}
public function testDatabaseTypeConfig()
{
$dialog = $this->getHelperMock();
// We specified an input value for hostname.
$dialog->expects($this->once())->method('ask')->willReturn('testedvalue');
$this->executeWithoutParam('--db-type', $dialog);
// Check that specified arguments are correctly loaded.
self::assertEquals('testedvalue', $this->config['b8']['database']['type']);
}
public function testDatabaseHostConfig()
{
$dialog = $this->getHelperMock();
// We specified an input value for hostname.
$dialog->expects($this->once())->method('ask')->willReturn('testedvalue');
$this->executeWithoutParam('--db-host', $dialog);
// Check that specified arguments are correctly loaded.
self::assertEquals('testedvalue', $this->config['b8']['database']['servers']['read'][0]['host']);
self::assertEquals('testedvalue', $this->config['b8']['database']['servers']['write'][0]['host']);
}
public function testDatabaseStringPortConfig()
{
$dialog = $this->getHelperMock();
// We specified an input value for hostname.
$dialog->expects($this->once())->method('ask')->willReturn('testedvalue');
$this->executeWithoutParam('--db-port', $dialog);
// Check that specified arguments are correctly loaded.
self::assertArrayNotHasKey('port', $this->config['b8']['database']['servers']['read'][0]);
self::assertArrayNotHasKey('port', $this->config['b8']['database']['servers']['write'][0]);
}
public function testDatabasePortConfig()
{
$dialog = $this->getHelperMock();
// We specified an input value for hostname.
$dialog->expects($this->once())->method('ask')->willReturn('333');
$this->executeWithoutParam('--db-port', $dialog);
// Check that specified arguments are correctly loaded.
self::assertEquals(333, $this->config['b8']['database']['servers']['read'][0]['port']);
self::assertEquals(333, $this->config['b8']['database']['servers']['write'][0]['port']);
}
public function testDatabaseNameConfig()
{
$dialog = $this->getHelperMock();
// We specified an input value for hostname.
$dialog->expects($this->once())->method('ask')->willReturn('testedvalue');
$this->executeWithoutParam('--db-name', $dialog);
// Check that specified arguments are correctly loaded.
self::assertEquals('testedvalue', $this->config['b8']['database']['name']);
}
public function testDatabaseUserConfig()
{
$dialog = $this->getHelperMock();
// We specified an input value for hostname.
$dialog->expects($this->once())->method('ask')->willReturn('testedvalue');
$this->executeWithoutParam('--db-user', $dialog);
// Check that specified arguments are correctly loaded.
self::assertEquals('testedvalue', $this->config['b8']['database']['username']);
}
public function testDatabasePasswordConfig()
{
$dialog = $this->getHelperMock();
$dialog->expects($this->once())->method('ask')->willReturn('testedvalue');
$this->executeWithoutParam('--db-password', $dialog);
// Check that specified arguments are correctly loaded.
self::assertEquals('testedvalue', $this->config['b8']['database']['password']);
}
public function testUrlConfig()
{
$dialog = $this->getHelperMock();
// We specified an input value for hostname.
$dialog->expects($this->once())->method('ask')->willReturn('http://testedvalue.com');
$this->executeWithoutParam('--url', $dialog);
// Check that specified arguments are correctly loaded.
self::assertEquals('http://testedvalue.com', $this->config['php-censor']['url']);
}
public function testAdminEmailConfig()
{
$dialog = $this->getHelperMock();
// We specified an input value for hostname.
$dialog->expects($this->once())->method('ask')->willReturn('admin@php-censor.local');
$this->executeWithoutParam('--admin-email', $dialog);
// Check that specified arguments are correctly loaded.
self::assertEquals('admin@php-censor.local', $this->admin['email']);
}
public function testAdminNameConfig()
{
$dialog = $this->getHelperMock();
// Define expectation for dialog.
$dialog->expects($this->once())->method('ask')->willReturn('testedvalue');
$this->executeWithoutParam('--admin-name', $dialog);
// Check that specified arguments are correctly loaded.
self::assertEquals('testedvalue', $this->admin['name']);
}
public function testAdminPasswordConfig()
{
$dialog = $this->getHelperMock();
// We specified an input value for hostname.
$dialog->expects($this->once())->method('ask')->willReturn('testedvalue');
$this->executeWithoutParam('--admin-password', $dialog);
// Check that specified arguments are correctly loaded.
self::assertEquals('testedvalue', $this->admin['password']);
}
}

View file

@ -0,0 +1,33 @@
<?php
namespace Tests\PHPCensor\Controller;
use PHPCensor\Controller\WebhookController;
class WebhookControllerTest extends \PHPUnit\Framework\TestCase
{
public function test_wrong_action_name_return_json_with_error()
{
$webController = new WebhookController(
$this->prophesize('PHPCensor\Config')->reveal(),
$this->prophesize('PHPCensor\Http\Request')->reveal(),
$this->prophesize('PHPCensor\Http\Response')->reveal()
);
$error = $webController->handleAction('test', []);
self::assertInstanceOf('PHPCensor\Http\Response\JsonResponse', $error);
$responseData = $error->getData();
self::assertEquals(500, $responseData['code']);
self::assertEquals('failed', $responseData['body']['status']);
self::assertEquals('application/json', $responseData['headers']['Content-Type']);
// @todo: we can't text the result is JSON file with
// self::assertJson((string) $error);
// since the flush method automatically add the header and break the
// testing framework.
}
}

237
tests/src/DatabaseMysqlTest.php Executable file
View file

@ -0,0 +1,237 @@
<?php
namespace Tests\PHPCensor;
use PHPCensor\Config;
use PHPCensor\Database;
class DatabaseMysqlTest extends \PHPUnit_Extensions_Database_TestCase
{
/**
* @var \PHPUnit_Extensions_Database_DB_DefaultDatabaseConnection|null
*/
protected $connection = null;
/**
* @param string $name
* @param array $data
* @param string $dataName
*/
public function __construct($name = null, array $data = [], $dataName = '')
{
parent::__construct($name, $data, $dataName);
if (extension_loaded('mysqli')) {
if (null === $this->connection) {
try {
$pdo = new \PDO(
'mysql:host=localhost;dbname=' . MYSQL_DBNAME,
MYSQL_USER,
MYSQL_PASSWORD
);
$this->connection = $this->createDefaultDBConnection($pdo, MYSQL_DBNAME);
$this->connection->getConnection()->query('
CREATE TABLE IF NOT EXISTS `databaseMysqlTest` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`projectId` int(11) NOT NULL,
`branch` varchar(250) NOT NULL DEFAULT \'master\',
`createDate` datetime,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
');
} catch (\PDOException $ex) {
$this->connection = null;
}
}
} else {
$this->connection = null;
}
}
/**
* @return \PHPUnit_Extensions_Database_DB_IDatabaseConnection
*/
protected function getConnection()
{
if (null === $this->connection) {
$this->markTestSkipped('Test skipped because MySQL database/user/extension doesn`t exist.');
}
return $this->connection;
}
/**
* @return \PHPUnit_Extensions_Database_DataSet_IDataSet
*/
protected function getDataSet()
{
return $this->createArrayDataSet([
'databaseMysqlTest' => [[
'id' => 1,
'projectId' => 1,
'branch' => 'master',
'createDate' => null,
], [
'id' => 2,
'projectId' => 2,
'branch' => 'dev',
'createDate' => '2018-02-20 01:01:01',
], [
'id' => 3,
'projectId' => 2,
'branch' => 'master',
'createDate' => '2018-02-21 02:02:02',
]],
]);
}
protected function setUp()
{
parent::setUp();
new Config([
'b8' => [
'database' => [
'servers' => [
'read' => [
['host' => 'localhost'],
],
'write' => [
['host' => 'localhost'],
],
],
'type' => Database::MYSQL_TYPE,
'name' => MYSQL_DBNAME,
'username' => MYSQL_USER,
'password' => MYSQL_PASSWORD,
],
],
]);
Database::reset();
}
public function testGetConnection()
{
$writeConnection = Database::getConnection('write');
$readConnection = Database::getConnection('read');
self::assertInstanceOf('\PHPCensor\Database', $writeConnection);
self::assertInstanceOf('\PHPCensor\Database', $readConnection);
$writeDetails = $writeConnection->getDetails();
self::assertTrue(is_array($writeDetails));
self::assertEquals(MYSQL_DBNAME, $writeDetails['db']);
self::assertEquals(MYSQL_USER, $writeDetails['user']);
self::assertEquals(MYSQL_PASSWORD, $writeDetails['pass']);
$readDetails = $readConnection->getDetails();
self::assertTrue(is_array($readDetails));
self::assertEquals(MYSQL_DBNAME, $readDetails['db']);
self::assertEquals(MYSQL_USER, $readDetails['user']);
self::assertEquals(MYSQL_PASSWORD, $readDetails['pass']);
self::assertEquals('mysql:host=localhost;dbname=b8_test', $readConnection->getDsn());
}
public function testGetWriteConnectionWithPort()
{
new Config([
'b8' => [
'database' => [
'servers' => [
'read' => [
[
'host' => 'localhost',
'port' => 3306,
],
],
'write' => [
[
'host' => 'localhost',
'port' => 3306,
],
],
],
'type' => Database::MYSQL_TYPE,
'name' => MYSQL_DBNAME,
'username' => MYSQL_USER,
'password' => MYSQL_PASSWORD,
],
],
]);
Database::reset();
$writeConnection = Database::getConnection('write');
$readConnection = Database::getConnection('read');
self::assertInstanceOf('\PHPCensor\Database', $writeConnection);
self::assertInstanceOf('\PHPCensor\Database', $readConnection);
self::assertEquals('mysql:host=localhost;port=3306;dbname=b8_test', $readConnection->getDsn());
}
/**
* @expectedException \Exception
*/
public function testConnectionFailure()
{
new Config([
'b8' => [
'database' => [
'servers' => [
'read' => [
['host' => 'localhost'],
],
'write' => [
['host' => 'localhost'],
],
],
'type' => Database::MYSQL_TYPE,
'name' => 'b8_test_2',
'username' => '',
'password' => '',
],
],
]);
Database::reset();
Database::getConnection('read');
}
public function testPrepareCommon()
{
$readConnection = Database::getConnection('read');
$sql = 'SELECT * FROM {{databaseMysqlTest}} WHERE {{projectId}} = :projectId';
$query = $readConnection->prepareCommon($sql);
$query->bindValue(':projectId', 1);
$query->execute();
$data = $query->fetchAll(\PDO::FETCH_ASSOC);
self::assertEquals(1, count($data));
self::assertEquals([[
'id' => 1,
'projectId' => 1,
'branch' => 'master',
'createDate' => null,
]], $data);
}
public function testLastInsertIdExtended()
{
$writeConnection = Database::getConnection('write');
$sql = 'INSERT INTO {{databaseMysqlTest}} ({{projectId}}) VALUES (3)';
$query = $writeConnection->prepareCommon($sql);
$query->execute();
self::assertEquals(4, $writeConnection->lastInsertIdExtended());
}
}

View file

@ -0,0 +1,241 @@
<?php
namespace Tests\PHPCensor;
use PHPCensor\Config;
use PHPCensor\Database;
class DatabasePostgresqlTest extends \PHPUnit_Extensions_Database_TestCase
{
/**
* @var \PHPUnit_Extensions_Database_DB_DefaultDatabaseConnection|null
*/
protected $connection = null;
/**
* @param string $name
* @param array $data
* @param string $dataName
*/
public function __construct($name = null, array $data = [], $dataName = '')
{
parent::__construct($name, $data, $dataName);
if (extension_loaded('pgsql')) {
if (null === $this->connection) {
try {
$pdo = new \PDO(
'pgsql:host=localhost;dbname=' . POSTGRESQL_DBNAME,
POSTGRESQL_USER,
POSTGRESQL_PASSWORD
);
$this->connection = $this->createDefaultDBConnection($pdo, POSTGRESQL_DBNAME);
$this->connection->getConnection()->query('
CREATE TABLE IF NOT EXISTS "databasePostgresqlTest" (
"id" SERIAL,
"projectId" integer NOT NULL,
"branch" character varying(250) NOT NULL DEFAULT \'master\',
"createDate" timestamp without time zone,
PRIMARY KEY ("id")
)
');
} catch (\PDOException $ex) {
$this->connection = null;
}
}
} else {
$this->connection = null;
}
}
/**
* @return \PHPUnit_Extensions_Database_DB_IDatabaseConnection
*/
protected function getConnection()
{
if (null === $this->connection) {
$this->markTestSkipped('Test skipped because PostgreSQL database/user/extension doesn`t exist.');
}
return $this->connection;
}
/**
* @return \PHPUnit_Extensions_Database_DataSet_IDataSet
*/
protected function getDataSet()
{
return $this->createArrayDataSet([
'databasePostgresqlTest' => [[
'id' => 1,
'projectId' => 1,
'branch' => 'master',
'createDate' => null,
], [
'id' => 2,
'projectId' => 2,
'branch' => 'dev',
'createDate' => '2018-02-20 01:01:01',
], [
'id' => 3,
'projectId' => 2,
'branch' => 'master',
'createDate' => '2018-02-21 02:02:02',
]],
]);
}
protected function setUp()
{
parent::setUp();
new Config([
'b8' => [
'database' => [
'servers' => [
'read' => [
['host' => 'localhost'],
],
'write' => [
['host' => 'localhost'],
],
],
'type' => Database::POSTGRESQL_TYPE,
'name' => POSTGRESQL_DBNAME,
'username' => POSTGRESQL_USER,
'password' => POSTGRESQL_PASSWORD,
],
],
]);
Database::reset();
}
public function testGetConnection()
{
$writeConnection = Database::getConnection('write');
$readConnection = Database::getConnection('read');
self::assertInstanceOf('\PHPCensor\Database', $writeConnection);
self::assertInstanceOf('\PHPCensor\Database', $readConnection);
$writeDetails = $writeConnection->getDetails();
self::assertTrue(is_array($writeDetails));
self::assertEquals(POSTGRESQL_DBNAME, $writeDetails['db']);
self::assertEquals(POSTGRESQL_USER, $writeDetails['user']);
self::assertEquals(POSTGRESQL_PASSWORD, $writeDetails['pass']);
$readDetails = $readConnection->getDetails();
self::assertTrue(is_array($readDetails));
self::assertEquals(POSTGRESQL_DBNAME, $readDetails['db']);
self::assertEquals(POSTGRESQL_USER, $readDetails['user']);
self::assertEquals(POSTGRESQL_PASSWORD, $readDetails['pass']);
self::assertEquals('pgsql:host=localhost;dbname=b8_test', $readConnection->getDsn());
}
public function testGetWriteConnectionWithPort()
{
new Config([
'b8' => [
'database' => [
'servers' => [
'read' => [
[
'host' => 'localhost',
'port' => 5432,
],
],
'write' => [
[
'host' => 'localhost',
'port' => 5432,
],
],
],
'type' => Database::POSTGRESQL_TYPE,
'name' => POSTGRESQL_DBNAME,
'username' => POSTGRESQL_USER,
'password' => POSTGRESQL_PASSWORD,
],
],
]);
Database::reset();
$writeConnection = Database::getConnection('write');
$readConnection = Database::getConnection('read');
self::assertInstanceOf('\PHPCensor\Database', $writeConnection);
self::assertInstanceOf('\PHPCensor\Database', $readConnection);
self::assertEquals('pgsql:host=localhost;port=5432;dbname=b8_test', $readConnection->getDsn());
}
/**
* @expectedException \Exception
*/
public function testConnectionFailure()
{
new Config([
'b8' => [
'database' => [
'servers' => [
'read' => [
['host' => 'localhost'],
],
'write' => [
['host' => 'localhost'],
],
],
'type' => Database::POSTGRESQL_TYPE,
'name' => 'b8_test_2',
'username' => '',
'password' => '',
],
],
]);
Database::reset();
Database::getConnection('read');
}
public function testPrepareCommon()
{
$readConnection = Database::getConnection('read');
$sql = 'SELECT * FROM {{databasePostgresqlTest}} WHERE {{projectId}} = :projectId';
$query = $readConnection->prepareCommon($sql);
$query->bindValue(':projectId', 1);
$query->execute();
$data = $query->fetchAll(\PDO::FETCH_ASSOC);
self::assertEquals(1, count($data));
self::assertEquals([[
'id' => 1,
'projectId' => 1,
'branch' => 'master',
'createDate' => null,
]], $data);
}
public function testLastInsertIdExtended()
{
$this->connection->getConnection()->query('
ALTER SEQUENCE "databasePostgresqlTest_id_seq" RESTART WITH 4;
');
$writeConnection = Database::getConnection('write');
$sql = 'INSERT INTO {{databasePostgresqlTest}} ({{projectId}}) VALUES (3)';
$query = $writeConnection->prepareCommon($sql);
$query->execute();
self::assertEquals(4, $writeConnection->lastInsertIdExtended('databasePostgresqlTest'));
}
}

202
tests/src/FormTest.php Executable file
View file

@ -0,0 +1,202 @@
<?php
namespace Tests\PHPCensor;
use PHPCensor\Form;
class FormTest extends \PHPUnit\Framework\TestCase
{
public function testFormBasics()
{
$f = new Form();
$f->setAction('/');
$f->setMethod('POST');
self::assertTrue($f->getAction() == '/');
self::assertTrue($f->getMethod() == 'POST');
}
public function testElementBasics()
{
$f = new Form\Element\Text('element-name');
$f->setId('element-id');
$f->setLabel('element-label');
$f->setClass('element-class');
$f->setContainerClass('container-class');
self::assertTrue($f->getName() == 'element-name');
self::assertTrue($f->getId() == 'element-id');
self::assertTrue($f->getLabel() == 'element-label');
self::assertTrue($f->getClass() == 'element-class');
self::assertTrue($f->getContainerClass() == 'container-class');
$output = $f->render();
self::assertTrue(is_string($output));
self::assertTrue(!empty($output));
self::assertTrue(strpos($output, 'container-class') !== false);
}
public function testInputBasics()
{
$f = new Form\Element\Text();
$f->setValue('input-value');
$f->setRequired(true);
$f->setValidator(function ($value) {
return ($value == 'input-value');
});
self::assertTrue($f->getValue() == 'input-value');
self::assertTrue($f->getRequired() == true);
self::assertTrue(is_callable($f->getValidator()));
}
public function testInputCreate()
{
$text = Form\Element\Text::create(
'input-name',
'input-label',
true
);
self::assertEquals('input-name', $text->getName());
self::assertEquals('input-label', $text->getLabel());
self::assertTrue($text->getRequired());
}
public function testInputValidation()
{
$f = new Form\Element\Text();
$f->setRequired(true);
self::assertFalse($f->validate());
$f->setRequired(false);
$f->setPattern('input\-value');
self::assertFalse($f->validate());
$f->setValue('input-value');
self::assertTrue($f->validate());
$f->setValidator(function ($item) {
if ($item != 'input-value') {
throw new \Exception('Invalid input value.');
}
});
self::assertTrue($f->validate());
$f->setValue('fail');
$f->setPattern(null);
self::assertFalse($f->validate());
}
public function testInputValidationWithCustomError()
{
$f = new Form\Element\Text();
$f->setRequired(true);
$f->setValue('input-value');
$f->setError('Error!');
self::assertFalse($f->validate());
}
public function testFieldSetBasics()
{
$f = new Form\FieldSet();
$f2 = new Form\FieldSet('group');
$f3 = new Form\FieldSet();
$t = new Form\Element\Text('one');
$t->setRequired(true);
$f2->addField($t);
$t = new Form\Element\Text('two');
$f2->addField($t);
$t = new Form\Element\Text('three');
$f3->addField($t);
$f->addField($f2);
$f->addField($f3);
self::assertFalse($f->validate());
$f->setValues(['group' => ['one' => 'ONE', 'two' => 'TWO'], 'three' => 'THREE']);
$values = $f->getValues();
self::assertTrue(is_array($values));
self::assertTrue(array_key_exists('group', $values));
self::assertTrue(array_key_exists('one', $values['group']));
self::assertTrue(array_key_exists('three', $values));
self::assertTrue($values['group']['one'] == 'ONE');
self::assertTrue($values['group']['two'] == 'TWO');
self::assertTrue($values['three'] == 'THREE');
self::assertTrue($f->validate());
$html = $f->render();
self::assertTrue(strpos($html, 'one') !== false);
self::assertTrue(strpos($html, 'two') !== false);
}
public function testElements()
{
$e = new Form\Element\Button();
self::assertTrue($e->validate());
self::assertTrue(strpos($e->render(), 'button') !== false);
$e = new Form\Element\Checkbox();
$e->setCheckedValue('ten');
self::assertTrue($e->getCheckedValue() == 'ten');
self::assertTrue(strpos($e->render(), 'checkbox') !== false);
self::assertTrue(strpos($e->render(), 'checked') === false);
$e->setValue(true);
self::assertTrue(strpos($e->render(), 'checked') !== false);
$e->setValue('ten');
self::assertTrue(strpos($e->render(), 'checked') !== false);
$e->setValue('fail');
self::assertTrue(strpos($e->render(), 'checked') === false);
$e = new Form\Element\CheckboxGroup();
self::assertTrue(strpos($e->render(), 'group') !== false);
$e = new Form\ControlGroup();
self::assertTrue(strpos($e->render(), 'group') !== false);
$e = new Form\Element\Email();
self::assertTrue(strpos($e->render(), 'email') !== false);
$e = new Form\Element\Select();
$e->setOptions(['key' => 'Val']);
$html = $e->render();
self::assertTrue(strpos($html, 'select') !== false);
self::assertTrue(strpos($html, 'option') !== false);
self::assertTrue(strpos($html, 'key') !== false);
self::assertTrue(strpos($html, 'Val') !== false);
$e = new Form\Element\Submit();
self::assertTrue($e->validate());
self::assertTrue(strpos($e->render(), 'submit') !== false);
$e = new Form\Element\Text();
$e->setValue('test');
self::assertTrue(strpos($e->render(), 'test') !== false);
$e = new Form\Element\TextArea();
$e->setRows(10);
self::assertTrue(strpos($e->render(), '10') !== false);
$e = new Form\Element\Url();
self::assertTrue(strpos($e->render(), 'url') !== false);
$e = new Form\Element\Password();
self::assertTrue(strpos($e->render(), 'password') !== false);
}
}

View file

@ -0,0 +1,18 @@
<?php
namespace Tests\PHPCensor\Helper;
use PHPCensor\Helper\AnsiConverter;
use PHPUnit\Framework\TestCase;
class AnsiConverterTest extends TestCase
{
public function testConvert_convertToHtml()
{
$input = "\e[31mThis is red !\e[0m";
$expectedOutput = '<span class="ansi_color_bg_black ansi_color_fg_red">This is red !</span>';
$actualOutput = AnsiConverter::convert($input);
self::assertEquals($expectedOutput, $actualOutput);
}
}

View file

@ -0,0 +1,48 @@
<?php
namespace Tests\PHPCensor\Helper;
use PHPCensor\Helper\BuildInterpolator;
class BuildInterpolatorTest extends \PHPUnit\Framework\TestCase
{
/**
* @var BuildInterpolator
*/
protected $testedInterpolator;
protected function setUp()
{
parent::setup();
$this->testedInterpolator = new BuildInterpolator();
}
public function testInterpolate_LeavesStringsUnchangedByDefault()
{
$string = "Hello World";
$expectedOutput = "Hello World";
$actualOutput = $this->testedInterpolator->interpolate($string);
self::assertEquals($expectedOutput, $actualOutput);
}
public function testInterpolate_LeavesStringsUnchangedWhenBuildIsSet()
{
$build = $this->prophesize('PHPCensor\\Model\\Build')->reveal();
$string = "Hello World";
$expectedOutput = "Hello World";
$this->testedInterpolator->setupInterpolationVars(
$build,
"/buildpath/",
"php-censor.local"
);
$actualOutput = $this->testedInterpolator->interpolate($string);
self::assertEquals($expectedOutput, $actualOutput);
}
}

View file

@ -0,0 +1,109 @@
<?php
namespace Tests\PHPCensor\Helper;
use PHPCensor\Helper\CommandExecutor;
class CommandExecutorTest extends \PHPUnit\Framework\TestCase
{
/**
* @var CommandExecutor
*/
protected $testedExecutor;
protected function setUp()
{
parent::setUp();
$mockBuildLogger = $this->prophesize('PHPCensor\Logging\BuildLogger');
$class = 'PHPCensor\Helper\CommandExecutor';
$this->testedExecutor = new $class($mockBuildLogger->reveal(), __DIR__);
}
public function testGetLastOutput_ReturnsOutputOfCommand()
{
$this->testedExecutor->executeCommand(['echo "%s"', 'Hello World']);
$output = $this->testedExecutor->getLastOutput();
self::assertEquals("Hello World", $output);
}
public function testGetLastOutput_ForgetsPreviousCommandOutput()
{
$this->testedExecutor->executeCommand(['echo "%s"', 'Hello World']);
$this->testedExecutor->executeCommand(['echo "%s"', 'Hello Tester']);
$output = $this->testedExecutor->getLastOutput();
self::assertEquals("Hello Tester", $output);
}
public function testExecuteCommand_ReturnsTrueForValidCommands()
{
$returnValue = $this->testedExecutor->executeCommand(['echo "%s"', 'Hello World']);
self::assertTrue($returnValue);
}
public function testExecuteCommand_ReturnsFalseForInvalidCommands()
{
$returnValue = $this->testedExecutor->executeCommand(['eerfdcvcho "%s" > /dev/null 2>&1', 'Hello World']);
self::assertFalse($returnValue);
}
/**
* Runs a script that generates an output that fills the standard error
* buffer first, followed by the standard output buffer. The function
* should be able to read from both streams, thereby preventing the child
* process from blocking because one of its buffers is full.
*/
public function testExecuteCommand_AlternatesBothBuffers()
{
$length = 80000;
$script = <<<EOD
/bin/sh -c 'data="$(printf %%${length}s | tr " " "-")"; >&2 echo "\$data"; >&1 echo "\$data"'
EOD;
$data = str_repeat("-", $length);
$returnValue = $this->testedExecutor->executeCommand([$script]);
self::assertTrue($returnValue);
self::assertEquals($data, trim($this->testedExecutor->getLastOutput()));
self::assertEquals($data, trim($this->testedExecutor->getLastError()));
}
/**
* @expectedException \Exception
* @expectedMessageRegex WorldWidePeace
*/
public function testFindBinary_ThrowsWhenNotFound()
{
$thisFileName = "WorldWidePeace";
$this->testedExecutor->findBinary($thisFileName);
}
public function testFindBinary_ReturnsNullWihQuietArgument()
{
$thisFileName = "WorldWidePeace";
self::assertFalse($this->testedExecutor->findBinary($thisFileName, true));
}
public function testReplaceIllegalCharacters()
{
self::assertEquals(
"start <20> end",
$this->testedExecutor->replaceIllegalCharacters(
"start \xf0\x9c\x83\x96 end"
)
);
self::assertEquals(
"start <20> end",
$this->testedExecutor->replaceIllegalCharacters(
"start \xF0\x9C\x83\x96 end"
)
);
self::assertEquals(
"start 123_X08<30>_X00<30>_Xa4<61>_5432 end",
$this->testedExecutor->replaceIllegalCharacters(
"start 123_X08\x08_X00\x00_Xa4\xa4_5432 end"
)
);
}
}

View file

@ -0,0 +1,58 @@
<?php
namespace Tests\PHPCensor\Helper;
use PHPCensor\Helper\MailerFactory;
/**
* Unit tests for the ProjectService class.
* @author Dan Cryer <dan@block8.co.uk>
*/
class MailerFactoryTest extends \PHPUnit\Framework\TestCase
{
public function setUp()
{
}
public function testExecute_TestGetMailConfig()
{
$config = [
'smtp_address' => 'mail.example.com',
'smtp_port' => 225,
'smtp_encryption' => 'tls',
'smtp_username' => 'php-censor-user',
'smtp_password' => 'php-censor-password',
'default_mailto_address' => 'admin@php-censor.local',
];
$factory = new MailerFactory(['email_settings' => $config]);
self::assertEquals($config['smtp_address'], $factory->getMailConfig('smtp_address'));
self::assertEquals($config['smtp_port'], $factory->getMailConfig('smtp_port'));
self::assertEquals($config['smtp_encryption'], $factory->getMailConfig('smtp_encryption'));
self::assertEquals($config['smtp_username'], $factory->getMailConfig('smtp_username'));
self::assertEquals($config['smtp_password'], $factory->getMailConfig('smtp_password'));
self::assertEquals($config['default_mailto_address'], $factory->getMailConfig('default_mailto_address'));
}
public function testExecute_TestMailer()
{
$config = [
'smtp_address' => 'mail.example.com',
'smtp_port' => 225,
'smtp_encryption' => 'tls',
'smtp_username' => 'php-censor-user',
'smtp_password' => 'php-censor-password',
'default_mailto_address' => 'admin@php-censor.local',
];
$factory = new MailerFactory(['email_settings' => $config]);
$mailer = $factory->getSwiftMailerFromConfig();
self::assertEquals($config['smtp_address'], $mailer->getTransport()->getHost());
self::assertEquals($config['smtp_port'], $mailer->getTransport()->getPort());
self::assertEquals('tls', $mailer->getTransport()->getEncryption());
self::assertEquals($config['smtp_username'], $mailer->getTransport()->getUsername());
self::assertEquals($config['smtp_password'], $mailer->getTransport()->getPassword());
}
}

86
tests/src/HttpExceptionTest.php Executable file
View file

@ -0,0 +1,86 @@
<?php
namespace Tests\PHPCensor;
use PHPCensor\Exception\HttpException;
class HttpExceptionTest extends \PHPUnit\Framework\TestCase
{
public function testHttpExceptionIsException()
{
$ex = new HttpException();
self::assertTrue($ex instanceof \Exception);
}
public function testHttpException()
{
try {
throw new HttpException('Test');
} catch (HttpException $ex) {
self::assertTrue($ex->getMessage() == 'Test');
self::assertTrue($ex->getErrorCode() == 500);
self::assertTrue($ex->getStatusMessage() == 'Internal Server Error');
self::assertTrue($ex->getHttpHeader() == 'HTTP/1.1 500 Internal Server Error');
}
}
public function testBadRequestException()
{
try {
throw new HttpException\BadRequestException('Test');
} catch (HttpException $ex) {
self::assertTrue($ex->getErrorCode() == 400);
self::assertTrue($ex->getStatusMessage() == 'Bad Request');
}
}
public function testForbiddenException()
{
try {
throw new HttpException\ForbiddenException('Test');
} catch (HttpException $ex) {
self::assertTrue($ex->getErrorCode() == 403);
self::assertTrue($ex->getStatusMessage() == 'Forbidden');
}
}
public function testNotAuthorizedException()
{
try {
throw new HttpException\NotAuthorizedException('Test');
} catch (HttpException $ex) {
self::assertTrue($ex->getErrorCode() == 401);
self::assertTrue($ex->getStatusMessage() == 'Not Authorized');
}
}
public function testNotFoundException()
{
try {
throw new HttpException\NotFoundException('Test');
} catch (HttpException $ex) {
self::assertTrue($ex->getErrorCode() == 404);
self::assertTrue($ex->getStatusMessage() == 'Not Found');
}
}
public function testServerErrorException()
{
try {
throw new HttpException\ServerErrorException('Test');
} catch (HttpException $ex) {
self::assertTrue($ex->getErrorCode() == 500);
self::assertTrue($ex->getStatusMessage() == 'Internal Server Error');
}
}
public function testValidationException()
{
try {
throw new HttpException\ValidationException('Test');
} catch (HttpException $ex) {
self::assertTrue($ex->getErrorCode() == 400);
self::assertTrue($ex->getStatusMessage() == 'Bad Request');
}
}
}

View file

@ -0,0 +1,106 @@
<?php
namespace Tests\PHPCensor\Logging;
use PHPCensor\Logging\BuildLogger;
use Prophecy\Argument;
use Psr\Log\LogLevel;
class BuildLoggerTest extends \PHPUnit\Framework\TestCase
{
/**
* @var BuildLogger
*/
protected $testedBuildLogger;
protected $mockLogger;
protected $mockBuild;
protected function setUp()
{
parent::setUp();
$this->mockLogger = $this->prophesize('\Psr\Log\LoggerInterface');
$this->mockBuild = $this->prophesize('\PHPCensor\Model\Build');
$this->testedBuildLogger = new BuildLogger(
$this->mockLogger->reveal(),
$this->mockBuild->reveal()
);
}
public function testLog_CallsWrappedLogger()
{
$level = LogLevel::NOTICE;
$message = "Testing";
$contextIn = [];
$this->mockLogger->log($level, $message, Argument::type('array'))
->shouldBeCalledTimes(1);
$this->testedBuildLogger->log($message, $level, $contextIn);
}
public function testLog_CallsWrappedLoggerForEachMessage()
{
$level = LogLevel::NOTICE;
$message = ["One", "Two", "Three"];
$contextIn = [];
$this->mockLogger->log($level, "One", Argument::type('array'))
->shouldBeCalledTimes(1);
$this->mockLogger->log($level, "Two", Argument::type('array'))
->shouldBeCalledTimes(1);
$this->mockLogger->log($level, "Three", Argument::type('array'))
->shouldBeCalledTimes(1);
$this->testedBuildLogger->log($message, $level, $contextIn);
}
public function testLog_AddsBuildToContext()
{
$level = LogLevel::NOTICE;
$message = "Testing";
$contextIn = [];
$expectedContext = [
'build' => $this->mockBuild->reveal()
];
$this->mockLogger->log($level, $message, $expectedContext)
->shouldBeCalledTimes(1);
$this->testedBuildLogger->log($message, $level, $contextIn);
}
public function testLogFailure_LogsAsErrorLevel()
{
$message = "Testing";
$expectedLevel = LogLevel::ERROR;
$this->mockLogger->log($expectedLevel,
Argument::type('string'),
Argument::type('array'))
->shouldBeCalledTimes(1);
$this->testedBuildLogger->logFailure($message);
}
public function testLogFailure_AddsExceptionContext()
{
$message = "Testing";
$exception = new \Exception("Expected Exception");
$this->mockLogger->log(Argument::type('string'),
Argument::type('string'),
Argument::withEntry('exception', $exception))
->shouldBeCalledTimes(1);
$this->testedBuildLogger->logFailure($message, $exception);
}
}

View file

@ -0,0 +1,157 @@
<?php
namespace Tests\PHPCensor\Model;
use PHPCensor\Exception\HttpException\ValidationException;
use PHPCensor\Model\Build;
/**
* Unit tests for the Build model class.
*
* @author Dan Cryer <dan@block8.co.uk>
*/
class BuildTest extends \PHPUnit\Framework\TestCase
{
public function testConstruct()
{
$build = new Build();
self::assertInstanceOf('PHPCensor\Model', $build);
self::assertInstanceOf('PHPCensor\Model\Build', $build);
$build = new Build([
'project_id' => 100,
'branch' => 'master',
]);
self::assertEquals([
'id' => null,
'project_id' => 100,
'commit_id' => null,
'status' => null,
'log' => null,
'branch' => 'master',
'tag' => null,
'create_date' => null,
'start_date' => null,
'finish_date' => null,
'committer_email' => null,
'commit_message' => null,
'extra' => null,
'environment' => null,
'source' => Build::SOURCE_UNKNOWN,
'user_id' => 0,
], $build->getDataArray());
try {
$build = new Build([
'project_id' => 101,
'branch' => 'dev',
'unknown' => 'unknown',
]);
} catch (\InvalidArgumentException $e) {
self::assertEquals(
'Model "PHPCensor\Model\Build" doesn\'t have field "unknown"',
$e->getMessage()
);
}
$build = new Build();
$build->setLog('log');
self::assertEquals('log', $build->getLog());
$build->setLog(null);
self::assertEquals(null, $build->getLog());
try {
$build->setLog([]);
} catch (ValidationException $e) {
self::assertEquals(
'Column "log" must be a string.',
$e->getMessage()
);
}
$build->setSource(Build::SOURCE_WEBHOOK_PULL_REQUEST);
self::assertEquals(Build::SOURCE_WEBHOOK_PULL_REQUEST, $build->getSource());
try {
$build->setSource('5');
} catch (ValidationException $e) {
self::assertEquals(
'Column "source" must be an integer.',
$e->getMessage()
);
}
try {
$build->setId(null);
} catch (ValidationException $e) {
self::assertEquals(
'Column "id" must not be null.',
$e->getMessage()
);
}
}
public function testExecute_TestBaseBuildDefaults()
{
$build = new Build();
self::assertEquals('#', $build->getCommitLink());
self::assertEquals('#', $build->getBranchLink());
self::assertEquals(null, $build->getFileLinkTemplate());
}
public function testExecute_TestIsSuccessful()
{
$build = new Build();
$build->setStatus(Build::STATUS_PENDING);
self::assertFalse($build->isSuccessful());
$build->setStatus(Build::STATUS_RUNNING);
self::assertFalse($build->isSuccessful());
$build->setStatus(Build::STATUS_FAILED);
self::assertFalse($build->isSuccessful());
$build->setStatus(Build::STATUS_SUCCESS);
self::assertTrue($build->isSuccessful());
}
public function testExecute_TestBuildExtra()
{
$info = [
'item1' => 'Item One',
'item2' => 2,
];
$build = new Build();
$build->setExtra(json_encode($info));
self::assertEquals('Item One', $build->getExtra('item1'));
self::assertEquals(2, $build->getExtra('item2'));
self::assertNull($build->getExtra('item3'));
self::assertEquals($info, $build->getExtra());
$build->setExtraValue('item3', 'Item Three');
self::assertEquals('Item One', $build->getExtra('item1'));
self::assertEquals('Item Three', $build->getExtra('item3'));
$build->setExtraValues([
'item3' => 'Item Three New',
'item4' => 4,
]);
self::assertEquals('Item One', $build->getExtra('item1'));
self::assertEquals('Item Three New', $build->getExtra('item3'));
self::assertEquals(4, $build->getExtra('item4'));
self::assertEquals([
'item1' => 'Item One',
'item2' => 2,
'item3' => 'Item Three New',
'item4' => 4,
], $build->getExtra());
}
}

View file

@ -0,0 +1,76 @@
<?php
namespace Tests\PHPCensor\Model;
use PHPCensor\Model\Project;
use PHPCensor\Model;
/**
* Unit tests for the Project model class.
*
* @author Dan Cryer <dan@block8.co.uk>
*/
class ProjectTest extends \PHPUnit\Framework\TestCase
{
public function testExecute_TestIsAValidModel()
{
$project = new Project();
self::assertTrue($project instanceof Model);
}
public function testExecute_TestGitDefaultBranch()
{
$project = new Project();
$project->setType('git');
self::assertEquals('master', $project->getBranch());
}
public function testExecute_TestGithubDefaultBranch()
{
$project = new Project();
$project->setType('github');
self::assertEquals('master', $project->getBranch());
}
public function testExecute_TestGitlabDefaultBranch()
{
$project = new Project();
$project->setType('gitlab');
self::assertEquals('master', $project->getBranch());
}
public function testExecute_TestBitbucketDefaultBranch()
{
$project = new Project();
$project->setType('bitbucket');
self::assertEquals('master', $project->getBranch());
}
public function testExecute_TestMercurialDefaultBranch()
{
$project = new Project();
$project->setType('hg');
self::assertEquals('default', $project->getBranch());
}
public function testExecute_TestProjectAccessInformation()
{
$info = [
'item1' => 'Item One',
'item2' => 2,
];
$project = new Project();
$project->setAccessInformation($info);
self::assertEquals('Item One', $project->getAccessInformation('item1'));
self::assertEquals(2, $project->getAccessInformation('item2'));
self::assertNull($project->getAccessInformation('item3'));
self::assertEquals($info, $project->getAccessInformation());
}
}

View file

@ -0,0 +1,356 @@
<?php
namespace Tests\PHPCensor\Plugin;
use PHPCensor\Config;
use PHPCensor\Plugin;
use PHPCensor\Plugin\Email as EmailPlugin;
use PHPCensor\Model\Build;
/**
* Unit test for the PHPUnit plugin.
*
* @author meadsteve
*/
class EmailTest extends \PHPUnit\Framework\TestCase
{
/**
* @var EmailPlugin $testedPhpUnit
*/
protected $testedEmailPlugin;
/**
* @var \PHPUnit_Framework_MockObject_MockObject $mockBuilder
*/
protected $mockBuilder;
/**
* @var \PHPUnit_Framework_MockObject_MockObject $mockBuild
*/
protected $mockBuild;
/**
* @var \PHPUnit_Framework_MockObject_MockObject $mockProject
*/
protected $mockProject;
/**
* @var int buildStatus
*/
public $buildStatus;
/**
* @var array $message;
*/
public $message;
/**
* @var bool $mailDelivered
*/
public $mailDelivered;
public function setUp()
{
$this->message = [];
$this->mailDelivered = true;
$self = $this;
$config = new Config([
'b8' => [
'view' => [
'path' => SRC_DIR . 'View/'
]
]
]);
$this->mockProject = $this
->getMockBuilder('\PHPCensor\Model\Project')
->setMethods(['getTitle'])
->setMockClassName('mockProject')
->disableOriginalConstructor()
->getMock();
$this->mockProject->expects($this->any())
->method('getTitle')
->will($this->returnValue("Test-Project"));
$this->mockBuild = $this
->getMockBuilder('\PHPCensor\Model\Build')
->setMethods(['getLog', 'getStatus', 'getProject', 'getCommitterEmail'])
->setMockClassName('mockBuild')
->disableOriginalConstructor()
->getMock();
$this->mockBuild->expects($this->any())
->method('getLog')
->will($this->returnValue("Build Log"));
$this->mockBuild->expects($this->any())
->method('getStatus')
->will($this->returnCallback(function () use ($self) {
return $self->buildStatus;
}));
$this->mockBuild->expects($this->any())
->method('getProject')
->will($this->returnValue($this->mockProject));
$this->mockBuild->expects($this->any())
->method('getCommitterEmail')
->will($this->returnValue('committer-email@example.com'));
$this->mockBuilder = $this
->getMockBuilder('\PHPCensor\Builder')
->setMethods(['getSystemConfig', 'getBuild', 'log', 'logDebug'])
->setMockClassName('mockBuilder_email')
->disableOriginalConstructor()
->getMock();
$this->mockBuilder->buildPath = "/";
$this->mockBuilder->expects($this->any())
->method('getSystemConfig')
->with('php-censor')
->will($this->returnValue(['email_settings' => ['from_address' => "test-from-address@example.com"]]));
}
protected function loadEmailPluginWithOptions($arrOptions = [], $buildStatus = null, $mailDelivered = 1)
{
$this->mailDelivered = $mailDelivered;
if (is_null($buildStatus)) {
$this->buildStatus = Build::STATUS_SUCCESS;
} else {
$this->buildStatus = $buildStatus;
}
// Reset current message.
$this->message = [];
$self = $this;
$this->testedEmailPlugin = $this
->getMockBuilder('\PHPCensor\Plugin\Email')
->setMethods(['sendEmail'])
->setConstructorArgs([$this->mockBuilder, $this->mockBuild, $arrOptions])
->getMock();
$this->testedEmailPlugin->expects($this->any())
->method('sendEmail')
->will($this->returnCallback(function ($to, $cc, $subject, $body) use ($self) {
$self->message['to'][] = $to;
$self->message['cc'] = $cc;
$self->message['subject'] = $subject;
$self->message['body'] = $body;
return $self->mailDelivered;
}));
}
public function testReturnsFalseWithoutArgs()
{
$this->loadEmailPluginWithOptions();
$returnValue = $this->testedEmailPlugin->execute();
// As no addresses will have been mailed as non are configured.
$expectedReturn = false;
self::assertEquals($expectedReturn, $returnValue);
}
public function testBuildsBasicEmails()
{
$this->loadEmailPluginWithOptions([
'addresses' => ['test-receiver@example.com']
], Build::STATUS_SUCCESS);
$this->testedEmailPlugin->execute();
self::assertContains('test-receiver@example.com', $this->message['to']);
}
public function testBuildsDefaultEmails()
{
$this->loadEmailPluginWithOptions([
'default_mailto_address' => 'default-mailto-address@example.com'
], Build::STATUS_SUCCESS);
$this->testedEmailPlugin->execute();
self::assertContains('default-mailto-address@example.com', $this->message['to']);
}
public function testExecute_UniqueRecipientsFromWithCommitter()
{
$this->loadEmailPluginWithOptions([
'addresses' => ['test-receiver@example.com', 'test-receiver2@example.com']
]);
$returnValue = $this->testedEmailPlugin->execute();
self::assertTrue($returnValue);
self::assertCount(2, $this->message['to']);
self::assertContains('test-receiver@example.com', $this->message['to']);
self::assertContains('test-receiver2@example.com', $this->message['to']);
}
public function testExecute_UniqueRecipientsWithCommitter()
{
$this->loadEmailPluginWithOptions([
'committer' => true,
'addresses' => ['test-receiver@example.com', 'committer@test.com']
]);
$returnValue = $this->testedEmailPlugin->execute();
self::assertTrue($returnValue);
self::assertContains('test-receiver@example.com', $this->message['to']);
self::assertContains('committer@test.com', $this->message['to']);
}
public function testCcDefaultEmails()
{
$this->loadEmailPluginWithOptions(
[
'default_mailto_address' => 'default-mailto-address@example.com',
'cc' => [
'cc-email-1@example.com',
'cc-email-2@example.com',
'cc-email-3@example.com',
],
],
Build::STATUS_SUCCESS
);
$this->testedEmailPlugin->execute();
self::assertEquals(
[
'cc-email-1@example.com',
'cc-email-2@example.com',
'cc-email-3@example.com',
],
$this->message['cc']
);
}
public function testBuildsCommitterEmails()
{
$this->loadEmailPluginWithOptions(
[
'committer' => true
],
Build::STATUS_SUCCESS
);
$this->testedEmailPlugin->execute();
self::assertContains('committer-email@example.com', $this->message['to']);
}
public function testMailSuccessfulBuildHaveProjectName()
{
$this->loadEmailPluginWithOptions(
[
'addresses' => ['test-receiver@example.com']
],
Build::STATUS_SUCCESS
);
$this->testedEmailPlugin->execute();
self::assertContains('Test-Project', $this->message['subject']);
self::assertContains('Test-Project', $this->message['body']);
}
public function testMailFailingBuildHaveProjectName()
{
$this->loadEmailPluginWithOptions(
[
'addresses' => ['test-receiver@example.com']
],
Build::STATUS_FAILED
);
$this->testedEmailPlugin->execute();
self::assertContains('Test-Project', $this->message['subject']);
self::assertContains('Test-Project', $this->message['body']);
}
public function testMailSuccessfulBuildHaveStatus()
{
$this->loadEmailPluginWithOptions(
[
'addresses' => ['test-receiver@example.com']
],
Build::STATUS_SUCCESS
);
self::assertEquals('local', $this->testedEmailPlugin->getPriorityPath());
$this->testedEmailPlugin->execute();
self::assertContains('Passing', $this->message['subject']);
self::assertContains('success', $this->message['body']);
}
public function testMailFailingBuildHaveStatus()
{
$this->loadEmailPluginWithOptions(
[
'addresses' => ['test-receiver@example.com'],
'priority_path' => 'global',
],
Build::STATUS_FAILED
);
self::assertEquals('global', $this->testedEmailPlugin->getPriorityPath());
$this->testedEmailPlugin->execute();
self::assertContains('Failing', $this->message['subject']);
self::assertContains('failed', $this->message['body']);
}
public function testMailDeliverySuccess()
{
$this->loadEmailPluginWithOptions(
[
'addresses' => ['test-receiver@example.com'],
'priority_path' => 'system',
],
Build::STATUS_FAILED,
1
);
self::assertEquals('system', $this->testedEmailPlugin->getPriorityPath());
$returnValue = $this->testedEmailPlugin->execute();
self::assertEquals(true, $returnValue);
}
public function testMailDeliveryFail()
{
$this->loadEmailPluginWithOptions(
[
'addresses' => ['test-receiver@example.com'],
'priority_path' => 'Global',
],
Build::STATUS_FAILED,
0
);
self::assertEquals('local', $this->testedEmailPlugin->getPriorityPath());
$returnValue = $this->testedEmailPlugin->execute();
self::assertEquals(false, $returnValue);
self::assertEquals('', Plugin::pluginName());
}
}

View file

@ -0,0 +1,124 @@
<?php
namespace Tests\PHPCensor\Plugin\Option;
use PHPCensor\Plugin\Option\PhpUnitOptions;
/**
* Unit test for the PHPUnitOptions parser
*
* @author Pablo Tejada <pablo@ptejada.com>
*/
class PhpUnitOptionsTest extends \PHPUnit\Framework\TestCase
{
public function validOptionsProvider()
{
return [
[
[
'config' => 'tests/phpunit.xml',
'args' => '--stop-on-error --log-junit /path/to/log/',
],
[
'stop-on-error' => '',
'log-junit' => '/path/to/log/',
'configuration' => 'tests/phpunit.xml',
],
],
[
[
'coverage' => '',
],
[],
],
[
[
'coverage' => '/path/to/coverage2/',
],
[
'coverage-html' => '/location',
'coverage-text' => null,
],
],
[
[
'coverage' => true,
'directory' => [
'/path/to/test1/',
'/path/to/test2/',
],
],
[
'coverage-html' => '/location',
'coverage-text' => null,
],
],
[
[
'config' => ['tests/phpunit.xml'],
'args' => "--testsuite=unit --bootstrap=vendor/autoload.php",
],
[
'testsuite' => 'unit',
'bootstrap' => 'vendor/autoload.php',
'configuration' => ['tests/phpunit.xml'],
],
],
[
[
'config' => ['tests/phpunit.xml'],
'args' => "--testsuite='unit' --bootstrap 'vendor/autoload.php'",
],
[
'testsuite' => 'unit',
'bootstrap' => 'vendor/autoload.php',
'configuration' => ['tests/phpunit.xml'],
],
],
[
[
'config' => ['tests/phpunit.xml'],
'args' => '--testsuite="unit" --bootstrap "vendor/autoload.php"',
],
[
'testsuite' => 'unit',
'bootstrap' => 'vendor/autoload.php',
'configuration' => ['tests/phpunit.xml'],
],
],
];
}
/**
* @param $rawOptions
* @param $parsedArguments
*
* @dataProvider validOptionsProvider
*/
public function testCommandArguments($rawOptions, $parsedArguments)
{
$options = new PhpUnitOptions($rawOptions, '/location');
self::assertSame($parsedArguments, $options->getCommandArguments());
}
public function testGetters()
{
$options = new PhpUnitOptions(
[
'run_from' => '/path/to/run/from',
'path' => 'subTest',
],
'/location'
);
self::assertEquals('/path/to/run/from', $options->getRunFrom());
self::assertEquals('subTest', $options->getTestsPath());
self::assertNull($options->getOption('random'));
self::assertEmpty($options->getDirectories());
self::assertEmpty($options->getConfigFiles());
$files = $options->getConfigFiles(ROOT_DIR);
self::assertFileExists(ROOT_DIR . $files[0]);
}
}

View file

@ -0,0 +1,200 @@
<?php
namespace Tests\PHPCensor\Plugin;
use PHPCensor\Plugin\Phar as PharPlugin;
use Phar as PHPPhar;
class PharTest extends \PHPUnit\Framework\TestCase
{
protected $directory;
protected function tearDown()
{
$this->cleanSource();
}
protected function getPlugin(array $options = [])
{
$build = $this
->getMockBuilder('PHPCensor\Model\Build')
->disableOriginalConstructor()
->getMock();
$builder = $this
->getMockBuilder('PHPCensor\Builder')
->disableOriginalConstructor()
->getMock();
return new PharPlugin($builder, $build, $options);
}
protected function buildTemp()
{
$directory = tempnam(ROOT_DIR . 'tests/runtime/', 'source');
unlink($directory);
return $directory;
}
protected function buildSource()
{
$directory = $this->buildTemp();
mkdir($directory);
file_put_contents($directory . '/one.php', '<?php echo "one";');
file_put_contents($directory . '/two.php', '<?php echo "two";');
mkdir($directory . '/config');
file_put_contents($directory . '/config/config.ini', '[config]');
mkdir($directory . '/views');
file_put_contents($directory . '/views/index.phtml', '<?php echo "hello";');
$this->directory = $directory;
return $directory;
}
protected function cleanSource()
{
if ($this->directory) {
$filenames = [
'/build.phar',
'/stub.php',
'/views/index.phtml',
'/views',
'/config/config.ini',
'/config',
'/two.php',
'/one.php',
];
foreach ($filenames as $filename) {
if (is_dir($this->directory . $filename)) {
rmdir($this->directory . $filename);
} else if (is_file($this->directory . $filename)) {
unlink($this->directory . $filename);
}
}
rmdir($this->directory);
$this->directory = null;
}
}
protected function checkReadonly()
{
if (ini_get('phar.readonly')) {
$this->markTestSkipped('Test skipped because phar writing disabled in php.ini.');
}
}
public function testPlugin()
{
$plugin = $this->getPlugin();
self::assertInstanceOf('PHPCensor\Plugin', $plugin);
self::assertInstanceOf('PHPCensor\Model\Build', $plugin->getBuild());
self::assertInstanceOf('PHPCensor\Builder', $plugin->getBuilder());
}
public function testDirectory()
{
$plugin = $this->getPlugin();
$plugin->getBuilder()->buildPath = 'foo';
self::assertEquals('foo', $plugin->getDirectory());
$plugin = $this->getPlugin(['directory' => 'dirname']);
self::assertEquals('dirname', $plugin->getDirectory());
}
public function testFilename()
{
$plugin = $this->getPlugin();
self::assertEquals('build.phar', $plugin->getFilename());
$plugin = $this->getPlugin(['filename' => 'another.phar']);
self::assertEquals('another.phar', $plugin->getFilename());
}
public function testRegExp()
{
$plugin = $this->getPlugin();
self::assertEquals('/\.php$/', $plugin->getRegExp());
$plugin = $this->getPlugin(['regexp' => '/\.(php|phtml)$/']);
self::assertEquals('/\.(php|phtml)$/', $plugin->getRegExp());
}
public function testStub()
{
$plugin = $this->getPlugin();
self::assertNull($plugin->getStub());
$plugin = $this->getPlugin(['stub' => 'stub.php']);
self::assertEquals('stub.php', $plugin->getStub());
}
public function testExecute()
{
$this->checkReadonly();
$plugin = $this->getPlugin();
$path = $this->buildSource();
$plugin->getBuilder()->buildPath = $path;
self::assertTrue($plugin->execute());
self::assertFileExists($path . '/build.phar');
PHPPhar::loadPhar($path . '/build.phar');
self::assertFileEquals($path . '/one.php', 'phar://build.phar/one.php');
self::assertFileEquals($path . '/two.php', 'phar://build.phar/two.php');
self::assertFileNotExists('phar://build.phar/config/config.ini');
self::assertFileNotExists('phar://build.phar/views/index.phtml');
}
public function testExecuteRegExp()
{
$this->checkReadonly();
$plugin = $this->getPlugin(['regexp' => '/\.(php|phtml)$/']);
$path = $this->buildSource();
$plugin->getBuilder()->buildPath = $path;
self::assertTrue($plugin->execute());
self::assertFileExists($path . '/build.phar');
PHPPhar::loadPhar($path . '/build.phar');
self::assertFileEquals($path . '/one.php', 'phar://build.phar/one.php');
self::assertFileEquals($path . '/two.php', 'phar://build.phar/two.php');
self::assertFileNotExists('phar://build.phar/config/config.ini');
self::assertFileEquals($path . '/views/index.phtml', 'phar://build.phar/views/index.phtml');
}
public function testExecuteStub()
{
$this->checkReadonly();
$content = <<<STUB
<?php
Phar::mapPhar();
__HALT_COMPILER(); ?>
STUB;
$path = $this->buildSource();
file_put_contents($path . '/stub.php', $content);
$plugin = $this->getPlugin(['stub' => 'stub.php']);
$plugin->getBuilder()->buildPath = $path;
self::assertTrue($plugin->execute());
self::assertFileExists($path . '/build.phar');
$phar = new PHPPhar($path . '/build.phar');
self::assertEquals($content, trim($phar->getStub())); // + trim because PHP adds newline char
}
public function testExecuteUnknownDirectory()
{
$this->checkReadonly();
$directory = $this->buildTemp();
$plugin = $this->getPlugin(['directory' => $directory]);
$plugin->getBuilder()->buildPath = $this->buildSource();
self::assertFalse($plugin->execute());
}
}

View file

@ -0,0 +1,118 @@
<?php
namespace Tests\PHPCensor\Plugin;
/**
* Unit test for the PHPUnit plugin.
*
* @author Pablo Tejada <pablo@ptejada.com>
*/
class PhpUnitTest extends \PHPUnit\Framework\TestCase
{
public function testSingleConfigFile()
{
$options = [
'config' => ROOT_DIR . 'phpunit.xml'
];
$mockPlugin = $this->getPluginBuilder($options)->setMethods(['runConfig'])->getMock();
$mockPlugin->expects($this->once())->method('runConfig')->with(null, ROOT_DIR . 'phpunit.xml');
$mockPlugin->execute();
}
public function testMultiConfigFile()
{
$options = [
'config' => [
ROOT_DIR . 'phpunit1.xml',
ROOT_DIR . 'phpunit2.xml',
]
];
$mockPlugin = $this->getPluginBuilder($options)->setMethods(['runConfig'])->getMock();
$mockPlugin->expects($this->exactly(2))->method('runConfig')->withConsecutive(
[null, ROOT_DIR . 'phpunit1.xml'],
[null, ROOT_DIR . 'phpunit2.xml']
);
$mockPlugin->execute();
}
/**
* @param array $options
*
* @return \PHPUnit_Framework_MockObject_MockBuilder
*/
protected function getPluginBuilder($options = [])
{
$loggerMock = $this->getMockBuilder('\Monolog\Logger')
->setConstructorArgs(['Test'])
->setMethods(['addRecord'])
->getMock();
$mockBuild = $this->getMockBuilder('\PHPCensor\Model\Build')->getMock();
$mockBuilder = $this->getMockBuilder('\PHPCensor\Builder')
->setConstructorArgs([$mockBuild, $loggerMock])
->setMethods(['executeCommand'])->getMock();
return $this->getMockBuilder('PHPCensor\Plugin\PhpUnit')->setConstructorArgs(
[$mockBuilder, $mockBuild, $options]
);
}
public function testSingleDir()
{
$options = [
'directory' => '/test/directory/one'
];
$mockPlugin = $this->getPluginBuilder($options)->setMethods(['runConfig'])->getMock();
$mockPlugin->expects($this->once())->method('runConfig')->with('/test/directory/one', null);
$mockPlugin->execute();
}
public function testMultiDir()
{
$options = [
'directory' => [
'/test/directory/one',
'/test/directory/two',
]
];
$mockPlugin = $this->getPluginBuilder($options)->setMethods(['runConfig'])->getMock();
$mockPlugin->expects($this->exactly(2))->method('runConfig')->withConsecutive(
['/test/directory/one'], ['/test/directory/two']
);
$mockPlugin->execute();
}
public function testProcessResultsFromConfig()
{
$options = [
'config' => ROOT_DIR . 'phpunit.xml'
];
$mockPlugin = $this->getPluginBuilder($options)->setMethods(['processResults'])->getMock();
$mockPlugin->expects($this->once())->method('processResults')->with($this->isType('string'));
$mockPlugin->execute();
}
public function testProcessResultsFromDir()
{
$options = [
'directory' => ROOT_DIR . 'Tests'
];
$mockPlugin = $this->getPluginBuilder($options)->setMethods(['processResults'])->getMock();
$mockPlugin->expects($this->once())->method('processResults')->with($this->isType('string'));
$mockPlugin->execute();
}
}

View file

@ -0,0 +1,231 @@
<?php
namespace Tests\PHPCensor\Plugin\Util;
use PHPCensor\Plugin\Util\Executor;
use Prophecy\Argument;
class ExecutorTest extends \PHPUnit\Framework\TestCase
{
/**
* @var Executor
*/
protected $testedExecutor;
protected $mockBuildLogger;
protected $mockFactory;
protected $mockStore;
protected function setUp()
{
parent::setUp();
$this->mockBuildLogger = $this->prophesize('\PHPCensor\Logging\BuildLogger');
$this->mockFactory = $this->prophesize('\PHPCensor\Plugin\Util\Factory');
$this->mockStore = $this->prophesize('\PHPCensor\Store\BuildStore');
$this->testedExecutor = new Executor(
$this->mockFactory->reveal(),
$this->mockBuildLogger->reveal(),
$this->mockStore->reveal()
);
}
protected function getFakePluginClassName($pluginName)
{
$pluginNamespace = 'Tests\\PHPCensor\\Plugin\\Util\\Fake\\';
return $pluginNamespace . $pluginName;
}
public function testExecutePlugin_AssumesNamespaceIfNoneGiven()
{
$options = [];
$pluginName = 'PhpUnit';
$pluginNamespace = 'PHPCensor\\Plugin\\';
$this->mockFactory
->buildPlugin($pluginNamespace . $pluginName, $options)
->shouldBeCalledTimes(1)
->willReturn($this->prophesize('PHPCensor\Plugin')->reveal());
$this->testedExecutor->executePlugin($pluginName, $options);
}
public function testExecutePlugin_KeepsCalledNameSpace()
{
$options = [];
$pluginClass = $this->getFakePluginClassName('ExamplePluginFull');
$this->mockFactory
->buildPlugin($pluginClass, $options)
->shouldBeCalledTimes(1)
->willReturn($this->prophesize('PHPCensor\Plugin')->reveal());
$this->testedExecutor->executePlugin($pluginClass, $options);
}
public function testExecutePlugin_CallsExecuteOnFactoryBuildPlugin()
{
$options = [];
$pluginName = 'PhpUnit';
$build = new \PHPCensor\Model\Build();
$mockPlugin = $this->prophesize('PHPCensor\Plugin');
$mockPlugin->execute()->shouldBeCalledTimes(1);
$this->mockFactory->buildPlugin(Argument::any(), Argument::any())->willReturn($mockPlugin->reveal());
$this->mockFactory->getResourceFor('PHPCensor\Model\Build')->willReturn($build);
$this->testedExecutor->executePlugin($pluginName, $options);
}
public function testExecutePlugin_ReturnsPluginSuccess()
{
$options = [];
$pluginName = 'PhpUnit';
$expectedReturnValue = true;
$mockPlugin = $this->prophesize('PHPCensor\Plugin');
$mockPlugin->execute()->willReturn($expectedReturnValue);
$this->mockFactory->buildPlugin(Argument::any(), Argument::any())->willReturn($mockPlugin->reveal());
$returnValue = $this->testedExecutor->executePlugin($pluginName, $options);
self::assertEquals($expectedReturnValue, $returnValue);
}
public function testExecutePlugin_LogsFailureForNonExistentClasses()
{
$options = [];
$pluginName = 'DOESNTEXIST';
$this->mockBuildLogger->logFailure(sprintf('Plugin does not exist: %s', $pluginName))->shouldBeCalledTimes(1);
$this->testedExecutor->executePlugin($pluginName, $options);
}
public function testExecutePlugin_LogsFailureWhenExceptionsAreThrownByPlugin()
{
$options = [];
$pluginName = 'PhpUnit';
$expectedException = new \RuntimeException("Generic Error");
$mockPlugin = $this->prophesize('PHPCensor\Plugin');
$mockPlugin->execute()->willThrow($expectedException);
$this->mockFactory->buildPlugin(Argument::any(), Argument::any())->willReturn($mockPlugin->reveal());
$this->mockBuildLogger->logFailure('Exception: ' . $expectedException->getMessage(), $expectedException)
->shouldBeCalledTimes(1);
$this->testedExecutor->executePlugin($pluginName, $options);
}
public function testExecutePlugins_CallsEachPluginForStage()
{
$phpUnitPluginOptions = [];
$behatPluginOptions = [];
$build = new \PHPCensor\Model\Build();
$config = [
'stageOne' => [
'PhpUnit' => $phpUnitPluginOptions,
'Behat' => $behatPluginOptions,
]
];
$pluginNamespace = 'PHPCensor\\Plugin\\';
$mockPhpUnitPlugin = $this->prophesize('PHPCensor\Plugin');
$mockPhpUnitPlugin->execute()->shouldBeCalledTimes(1)->willReturn(true);
$this->mockFactory->buildPlugin($pluginNamespace . 'PhpUnit', $phpUnitPluginOptions)
->willReturn($mockPhpUnitPlugin->reveal());
$this->mockFactory->getResourceFor('PHPCensor\Model\Build')->willReturn($build);
$mockBehatPlugin = $this->prophesize('PHPCensor\Plugin');
$mockBehatPlugin->execute()->shouldBeCalledTimes(1)->willReturn(true);
$this->mockFactory->buildPlugin($pluginNamespace . 'Behat', $behatPluginOptions)
->willReturn($mockBehatPlugin->reveal());
$this->testedExecutor->executePlugins($config, 'stageOne');
}
public function testGetBranchSpecificConfig()
{
$config = [
'setup' => [
'composer' => 'install',
]
];
self::assertEquals([], $this->testedExecutor->getBranchSpecificConfig($config, 'branch-1'));
$config = [
'setup' => [
'composer' => 'install',
],
'branch-branch-1' => [
'phpunit' => [],
],
];
self::assertEquals(['phpunit' => []], $this->testedExecutor->getBranchSpecificConfig($config, 'branch-1'));
$config = [
'setup' => [
'composer' => 'install',
],
'branch-branch-2' => [
'phpunit' => [],
],
];
self::assertEquals([], $this->testedExecutor->getBranchSpecificConfig($config, 'branch-1'));
$config = [
'setup' => [
'composer' => [
'install',
],
],
'branch-regex:.+' => [
'phpunit' => [],
],
];
self::assertEquals(['phpunit' => []], $this->testedExecutor->getBranchSpecificConfig($config, 'branch-1'));
$config = [
'setup' => [
'composer' => [
'install',
],
],
'branch-regex:^branch\-\d$' => [
'phpunit' => [],
],
];
self::assertEquals(['phpunit' => []], $this->testedExecutor->getBranchSpecificConfig($config, 'branch-1'));
$config = [
'setup' => [
'composer' => [
'install',
],
],
'branch-regex:^branch\-\w{2,}$' => [
'phpunit' => [],
],
];
self::assertEquals([], $this->testedExecutor->getBranchSpecificConfig($config, 'branch-1'));
}
}

View file

@ -0,0 +1,166 @@
<?php
namespace Tests\PHPCensor\Plugin\Util;
use PHPCensor\Plugin\Util\Factory;
class FactoryTest extends \PHPUnit\Framework\TestCase {
/**
* @var \PHPCensor\Plugin\Util\Factory
*/
protected $testedFactory;
protected $expectedResource;
protected $resourceLoader;
protected function setUp()
{
$this->testedFactory = new Factory();
// Setup a resource that can be returned and asserted against
$this->expectedResource = new \stdClass();
$resourceLink = $this->expectedResource;
$this->resourceLoader = function() use (&$resourceLink) {
return $resourceLink;
};
}
protected function tearDown()
{
// Nothing to do.
}
public function testRegisterResourceThrowsExceptionWithoutTypeAndName()
{
$this->setExpectedException('InvalidArgumentException', 'Type or Name must be specified');
$this->testedFactory->registerResource($this->resourceLoader, null, null);
}
public function testRegisterResourceThrowsExceptionIfLoaderIsntFunction()
{
$this->setExpectedException('InvalidArgumentException', '$loader is expected to be a function');
$this->testedFactory->registerResource(["dummy"], "TestName", "TestClass");
}
public function testBuildPluginWorksWithSingleOptionalArgConstructor()
{
$pluginClass = $this->getFakePluginClassName('ExamplePluginWithSingleOptionalArg');
$plugin = $this->testedFactory->buildPlugin($pluginClass);
self::assertInstanceOf($pluginClass, $plugin);
}
public function testBuildPluginThrowsExceptionIfMissingResourcesForRequiredArg()
{
$this->setExpectedException(
'DomainException',
'Unsatisfied dependency: requiredArgument'
);
$pluginClass = $this->getFakePluginClassName('ExamplePluginWithSingleRequiredArg');
$plugin = $this->testedFactory->buildPlugin($pluginClass);
}
public function testBuildPluginLoadsArgumentsBasedOnName()
{
$pluginClass = $this->getFakePluginClassName('ExamplePluginWithSingleRequiredArg');
$this->testedFactory->registerResource(
$this->resourceLoader,
"requiredArgument"
);
/** @var ExamplePluginWithSingleRequiredArg $plugin */
$plugin = $this->testedFactory->buildPlugin($pluginClass);
self::assertEquals($this->expectedResource, $plugin->RequiredArgument);
}
public function testBuildPluginLoadsArgumentsBasedOnType()
{
$pluginClass = $this->getFakePluginClassName('ExamplePluginWithSingleTypedRequiredArg');
$this->testedFactory->registerResource(
$this->resourceLoader,
null,
"stdClass"
);
/** @var ExamplePluginWithSingleTypedRequiredArg $plugin */
$plugin = $this->testedFactory->buildPlugin($pluginClass);
self::assertEquals($this->expectedResource, $plugin->RequiredArgument);
}
public function testBuildPluginLoadsFullExample()
{
$pluginClass = $this->getFakePluginClassName('ExamplePluginFull');
$this->registerBuildAndBuilder();
/** @var ExamplePluginFull $plugin */
$plugin = $this->testedFactory->buildPlugin($pluginClass);
self::assertInstanceOf($pluginClass, $plugin);
}
public function testBuildPluginLoadsFullExampleWithOptions()
{
$pluginClass = $this->getFakePluginClassName('ExamplePluginFull');
$expectedArgs = [
'thing' => "stuff"
];
$this->registerBuildAndBuilder();
/** @var ExamplePluginFull $plugin */
$plugin = $this->testedFactory->buildPlugin(
$pluginClass,
$expectedArgs
);
self::assertInternalType('array', $plugin->options);
self::assertArrayHasKey('thing', $plugin->options);
}
/**
* Registers mocked Builder and Build classes so that realistic plugins
* can be tested.
*/
private function registerBuildAndBuilder()
{
$self = $this;
$this->testedFactory->registerResource(
function () use ($self) {
return $self
->getMockBuilder('PHPCensor\Builder')
->disableOriginalConstructor()
->getMock();
},
null,
'PHPCensor\\Builder'
);
$this->testedFactory->registerResource(
function () use ($self) {
return $self
->getMockBuilder('PHPCensor\Model\Build')
->disableOriginalConstructor()
->getMock();
},
null,
'PHPCensor\\Model\\Build'
);
}
protected function getFakePluginClassName($pluginName)
{
$pluginNamespace = '\\Tests\\PHPCensor\\Plugin\\Util\\Fake\\';
return $pluginNamespace . $pluginName;
}
}

View file

@ -0,0 +1,32 @@
<?php
namespace Tests\PHPCensor\Plugin\Util\Fake;
use PHPCensor\Builder;
use PHPCensor\Model\Build;
use PHPCensor\Plugin;
class ExamplePluginFull extends Plugin {
/**
* @var array
*/
public $options;
/**
* @return string
*/
public static function pluginName()
{
return 'example_plugin_full';
}
public function __construct(Builder $builder, Build $build, array $options = [])
{
$this->options = $options;
}
public function execute()
{
}
}

View file

@ -0,0 +1,20 @@
<?php
namespace Tests\PHPCensor\Plugin\Util\Fake;
use PHPCensor\Plugin;
class ExamplePluginWithNoConstructorArgs extends Plugin
{
/**
* @return string
*/
public static function pluginName()
{
return 'example_plugin_with_no_constructor_args';
}
public function execute()
{
}
}

View file

@ -0,0 +1,26 @@
<?php
namespace Tests\PHPCensor\Plugin\Util\Fake;
use PHPCensor\Plugin;
class ExamplePluginWithSingleOptionalArg extends Plugin
{
/**
* @return string
*/
public static function pluginName()
{
return 'example_plugin_with_single_optional_arg';
}
function __construct($optional = null)
{
}
public function execute()
{
}
}

View file

@ -0,0 +1,28 @@
<?php
namespace Tests\PHPCensor\Plugin\Util\Fake;
use PHPCensor\Plugin;
class ExamplePluginWithSingleRequiredArg extends Plugin
{
/**
* @return string
*/
public static function pluginName()
{
return 'example_plugin_with_single_required_arg';
}
public $RequiredArgument;
function __construct($requiredArgument)
{
$this->RequiredArgument = $requiredArgument;
}
public function execute()
{
}
}

View file

@ -0,0 +1,28 @@
<?php
namespace Tests\PHPCensor\Plugin\Util\Fake;
use PHPCensor\Plugin;
class ExamplePluginWithSingleTypedRequiredArg extends Plugin
{
/**
* @return string
*/
public static function pluginName()
{
return 'example_plugin_with_single_typed_required_arg';
}
public $RequiredArgument;
function __construct(\stdClass $requiredArgument)
{
$this->RequiredArgument = $requiredArgument;
}
public function execute()
{
}
}

View file

@ -0,0 +1,90 @@
<?php
namespace Tests\PHPCensor\Plugin\Util;
use PHPCensor\Plugin\Util\PhpUnitResult;
use PHPCensor\Plugin\Util\PhpUnitResultJson;
use PHPCensor\Plugin\Util\PhpUnitResultJunit;
/**
* Class PhpUnitResultTest parses the results for the PhpUnitV2 plugin
*
* @author Pablo Tejada <pablo@ptejada.com>
*/
class PhpUnitResultTest extends \PHPUnit\Framework\TestCase
{
/**
* Skipped test results
*
* @var array[]
*/
static $skipped = [];
/**
* @dataProvider getTestData
*/
public function testInitParse($resultClass, $testFile)
{
$buildPath = '/path/to/build';
$parser = new $resultClass(ROOT_DIR . $testFile, $buildPath);
$output = $parser->parse()->getResults();
$errors = $parser->getErrors();
self::assertEquals(7, $parser->getFailures());
self::assertInternalType('array', $output);
self::assertInternalType('array', $errors);
self::assertNotEmpty($output);
self::assertNotEmpty($errors);
// The trace elements should not include the build path
self::assertStringStartsNotWith($buildPath, $output[3]['trace'][0]);
self::assertStringStartsNotWith($buildPath, $output[3]['trace'][1]);
self::assertEquals("some output\nfrom f4", $output[7]['output']);
self::assertEquals("has output\non lines", $output[15]['output']);
self::assertEquals(PhpUnitResult::SEVERITY_SKIPPED, $output[5]['severity']);
try {
self::assertContains('Incomplete Test:', $output[5]['message']);
} catch (\PHPUnit_Framework_ExpectationFailedException $e) {
self::$skipped[] = ['cls' => $resultClass, 'ex' => $e];
} catch (\PHPUnit\Framework\ExpectationFailedException $e) {
self::$skipped[] = ['cls' => $resultClass, 'ex' => $e];
}
self::assertEquals(PhpUnitResult::SEVERITY_SKIPPED, $output[11]['severity']);
try {
self::assertContains('Skipped Test:', $output[11]['message']);
} catch (\PHPUnit_Framework_ExpectationFailedException $e) {
self::$skipped[] = ['cls' => $resultClass, 'ex' => $e];
} catch (\PHPUnit\Framework\ExpectationFailedException $e) {
self::$skipped[] = ['cls' => $resultClass, 'ex' => $e];
}
}
/**
* used as long as junit format does not provide message for skipped tests
*/
public function testSkippedAnything()
{
if (self::$skipped) {
$msg = "Skipped result tests:\n";
foreach (self::$skipped as $skip) {
$exMsg = strstr((string)$skip['ex'], "\n", true);
if (false === $exMsg) {
$exMsg = (string)$skip['ex'];
}
$msg .= sprintf(" * %s: %s \n", $skip['cls'], $exMsg);
}
$this->markTestSkipped($msg);
}
}
public static function getTestData()
{
return [
'json' => [PhpUnitResultJson::class, 'tests/data/Plugin/PhpUnit/phpunit_money.txt'],
'junit' => [PhpUnitResultJunit::class, 'tests/data/Plugin/PhpUnit/phpunit_money_junit.xml'],
];
}
}

View file

@ -0,0 +1,18 @@
<?php
namespace Tests\PHPCensor\ProcessControl;
use PHPCensor\ProcessControl\PosixProcessControl;
class PosixProcessControlTest extends UnixProcessControlTest
{
protected function setUp()
{
$this->object = new PosixProcessControl();
}
public function testIsAvailable()
{
self::assertEquals(function_exists('posix_kill'), PosixProcessControl::isAvailable());
}
}

View file

@ -0,0 +1,127 @@
<?php
namespace Tests\PHPCensor\ProcessControl;
/**
* Some helpers to
*/
abstract class ProcessControlTest extends \PHPUnit\Framework\TestCase
{
/**
* @var resource
*/
protected $process;
/**
* @var array
*/
protected $pipes;
/**
* @var \PHPCensor\ProcessControl\ProcessControlInterface
*/
protected $object;
/** Starts a process.
*
* @return int The PID of the process.
*/
protected function startProcess()
{
$desc = [["pipe", "r"], ["pipe", "w"], ["pipe", "w"]];
$this->pipes = [];
$this->process = proc_open($this->getTestCommand(), $desc, $this->pipes);
sleep(1);
self::assertTrue(is_resource($this->process));
self::assertTrue($this->isRunning());
$status = proc_get_status($this->process);
return (integer)$status['pid'];
}
/** End the running process.
*
* @return int
*/
protected function endProcess()
{
if (!is_resource($this->process)) {
return;
}
array_map('fclose', $this->pipes);
$exitCode = proc_close($this->process);
self::assertFalse($this->isRunning());
$this->process = null;
return $exitCode;
}
/**
* @return bool
*/
protected function isRunning()
{
if (!is_resource($this->process)) {
return false;
}
$status = proc_get_status($this->process);
return (boolean)$status['running'];
}
public function testIsRunning()
{
if (!$this->object->isAvailable()) {
$this->markTestSkipped();
}
$pid = $this->startProcess();
self::assertTrue($this->object->isRunning($pid));
fwrite($this->pipes[0], PHP_EOL);
$exitCode = $this->endProcess();
self::assertEquals(0, $exitCode);
self::assertFalse($this->object->isRunning($pid));
}
public function testSoftKill()
{
if (!$this->object->isAvailable()) {
$this->markTestSkipped();
}
$pid = $this->startProcess();
self::assertTrue($this->object->kill($pid));
sleep(1);
self::assertFalse($this->isRunning());
}
public function testForcefullyKill()
{
if (!$this->object->isAvailable()) {
$this->markTestSkipped();
}
$pid = $this->startProcess();
$this->object->kill($pid, true);
sleep(1);
self::assertFalse($this->isRunning());
}
abstract public function testIsAvailable();
abstract public function getTestCommand();
protected function tearDown()
{
parent::tearDown();
$this->endProcess();
}
}

View file

@ -0,0 +1,23 @@
<?php
namespace Tests\PHPCensor\ProcessControl;
use PHPCensor\ProcessControl\UnixProcessControl;
class UnixProcessControlTest extends ProcessControlTest
{
protected function setUp()
{
$this->object = new UnixProcessControl();
}
public function getTestCommand()
{
return "read SOMETHING";
}
public function testIsAvailable()
{
self::assertEquals(DIRECTORY_SEPARATOR === '/', UnixProcessControl::isAvailable());
}
}

View file

@ -0,0 +1,63 @@
<?php
namespace Tests\PHPCensor\Security\Authentication;
use PHPCensor\Security\Authentication\Service;
class ServiceTest extends \PHPUnit\Framework\TestCase
{
public function testGetInstance()
{
self::assertInstanceOf('\PHPCensor\Security\Authentication\Service', Service::getInstance());
}
public function testBuildBuiltinProvider()
{
$provider = Service::buildProvider('test', ['type' => 'internal']);
self::assertInstanceOf('\PHPCensor\Security\Authentication\UserProvider\Internal', $provider);
}
public function testBuildAnyProvider()
{
$config = ['type' => '\Tests\PHPCensor\Security\Authentication\DummyProvider'];
$provider = Service::buildProvider("test", $config);
self::assertInstanceOf('\Tests\PHPCensor\Security\Authentication\DummyProvider', $provider);
self::assertEquals('test', $provider->key);
self::assertEquals($config, $provider->config);
}
public function testGetProviders()
{
$a = $this->prophesize('\PHPCensor\Security\Authentication\UserProviderInterface')->reveal();
$b = $this->prophesize('\PHPCensor\Security\Authentication\UserProviderInterface')->reveal();
$providers = ['a' => $a, 'b' => $b];
$service = new Service($providers);
self::assertEquals($providers, $service->getProviders());
}
public function testGetLoginPasswordProviders()
{
$a = $this->prophesize('\PHPCensor\Security\Authentication\UserProviderInterface')->reveal();
$b = $this->prophesize('\PHPCensor\Security\Authentication\LoginPasswordProviderInterface')->reveal();
$providers = ['a' => $a, 'b' => $b];
$service = new Service($providers);
self::assertEquals(['b' => $b], $service->getLoginPasswordProviders());
}
}
class DummyProvider
{
public $key;
public $config;
public function __construct($key, array $config)
{
$this->key = $key;
$this->config = $config;
}
}

View file

@ -0,0 +1,49 @@
<?php
namespace Tests\PHPCensor\Security\Authentication\UserProvider;
use PHPCensor\Model\User;
use PHPCensor\Security\Authentication\UserProvider\Internal;
class InternalTest extends \PHPUnit\Framework\TestCase
{
/**
* @var Internal
*/
protected $provider;
protected function setUp()
{
$this->provider = new Internal('internal', [
'type' => 'internal',
]);
}
public function testVerifyPassword()
{
$user = new User();
$password = 'bla';
$user->setHash(password_hash($password, PASSWORD_DEFAULT));
self::assertTrue($this->provider->verifyPassword($user, $password));
}
public function testVerifyInvaldPassword()
{
$user = new User();
$password = 'foo';
$user->setHash(password_hash($password, PASSWORD_DEFAULT));
self::assertFalse($this->provider->verifyPassword($user, 'bar'));
}
public function testCheckRequirements()
{
$this->provider->checkRequirements();
}
public function testProvisionUser()
{
self::assertNull($this->provider->provisionUser('john@doe.com'));
}
}

View file

@ -0,0 +1,182 @@
<?php
namespace Tests\PHPCensor\Service;
use PHPCensor\Model\Build;
use PHPCensor\Service\BuildService;
/**
* Unit tests for the ProjectService class.
*
* @author Dan Cryer <dan@block8.co.uk>
*/
class BuildServiceTest extends \PHPUnit\Framework\TestCase
{
/**
* @var BuildService $testedService
*/
protected $testedService;
/**
* @var \ $mockBuildStore
*/
protected $mockBuildStore;
/**
* @var \ $mockEnvironmentStore
*/
protected $mockEnvironmentStore;
public function setUp()
{
$this->mockBuildStore = $this->getMockBuilder('PHPCensor\Store\BuildStore')->getMock();
$this->mockBuildStore
->expects($this->any())
->method('save')
->will($this->returnArgument(0));
$this->mockEnvironmentStore = $this->getMockBuilder('PHPCensor\Store\EnvironmentStore')->getMock();
$this->mockEnvironmentStore
->expects($this->any())
->method('getByProjectId')
->will($this->returnValue(['items' => [], 'count' => 0]));
$this->testedService = new BuildService($this->mockBuildStore);
}
public function testExecute_CreateBasicBuild()
{
$project = $this
->getMockBuilder('PHPCensor\Model\Project')
->setMethods(['getEnvironmentStore'])
->getMock();
$project->expects($this->any())
->method('getEnvironmentStore')
->will($this->returnValue($this->mockEnvironmentStore));
$project->setType('github');
$project->setId(101);
$returnValue = $this->testedService->createBuild($project, null);
self::assertEquals(101, $returnValue->getProjectId());
self::assertEquals(Build::STATUS_PENDING, $returnValue->getStatus());
self::assertNull($returnValue->getStartDate());
self::assertNull($returnValue->getFinishDate());
self::assertNull($returnValue->getLog());
self::assertEquals(null, $returnValue->getCommitMessage());
self::assertNull($returnValue->getCommitterEmail());
self::assertEquals(['branches' => []], $returnValue->getExtra());
self::assertEquals('master', $returnValue->getBranch());
self::assertInstanceOf('DateTime', $returnValue->getCreateDate());
self::assertEquals('', $returnValue->getCommitId());
self::assertEquals(Build::SOURCE_UNKNOWN, $returnValue->getSource());
}
public function testExecute_CreateBuildWithOptions()
{
$project = $this
->getMockBuilder('PHPCensor\Model\Project')
->setMethods(['getEnvironmentStore'])
->getMock();
$project->expects($this->any())
->method('getEnvironmentStore')
->will($this->returnValue($this->mockEnvironmentStore));
$project->setType('hg');
$project->setId(101);
$returnValue = $this->testedService->createBuild(
$project,
null,
'123',
'testbranch',
null,
'test@example.com',
'test'
);
self::assertEquals('testbranch', $returnValue->getBranch());
self::assertEquals('123', $returnValue->getCommitId());
self::assertEquals('test', $returnValue->getCommitMessage());
self::assertEquals('test@example.com', $returnValue->getCommitterEmail());
}
public function testExecute_CreateBuildWithExtra()
{
$project = $this
->getMockBuilder('PHPCensor\Model\Project')
->setMethods(['getEnvironmentStore'])
->getMock();
$project->expects($this->any())
->method('getEnvironmentStore')
->will($this->returnValue($this->mockEnvironmentStore));
$project->setType('bitbucket');
$project->setId(101);
$returnValue = $this->testedService->createBuild(
$project,
null,
'',
null,
null,
null,
null,
Build::SOURCE_UNKNOWN,
0,
['item1' => 1001]
);
self::assertEquals(1001, $returnValue->getExtra('item1'));
}
public function testExecute_CreateDuplicateBuild()
{
$build = new Build();
$build->setId(1);
$build->setProjectId(101);
$build->setCommitId('abcde');
$build->setStatus(Build::STATUS_FAILED);
$build->setLog('Test');
$build->setBranch('example_branch');
$build->setStartDate(new \DateTime());
$build->setFinishDate(new \DateTime());
$build->setCommitMessage('test');
$build->setCommitterEmail('test@example.com');
$build->setExtra(json_encode(['item1' => 1001]));
$returnValue = $this->testedService->createDuplicateBuild($build);
self::assertNotEquals($build->getId(), $returnValue->getId());
self::assertEquals($build->getProjectId(), $returnValue->getProjectId());
self::assertEquals($build->getCommitId(), $returnValue->getCommitId());
self::assertNotEquals($build->getStatus(), $returnValue->getStatus());
self::assertEquals(Build::STATUS_PENDING, $returnValue->getStatus());
self::assertNull($returnValue->getLog());
self::assertEquals($build->getBranch(), $returnValue->getBranch());
self::assertNotEquals($build->getCreateDate(), $returnValue->getCreateDate());
self::assertNull($returnValue->getStartDate());
self::assertNull($returnValue->getFinishDate());
self::assertEquals('test', $returnValue->getCommitMessage());
self::assertEquals('test@example.com', $returnValue->getCommitterEmail());
self::assertEquals($build->getExtra('item1'), $returnValue->getExtra('item1'));
}
public function testExecute_DeleteBuild()
{
$store = $this->getMockBuilder('PHPCensor\Store\BuildStore')->getMock();
$store->expects($this->once())
->method('delete')
->will($this->returnValue(true));
$service = new BuildService($store);
$build = new Build();
self::assertEquals(true, $service->deleteBuild($build));
}
}

View file

@ -0,0 +1,208 @@
<?php
namespace Tests\PHPCensor\Service;
use PHPCensor\Model\Build;
use PHPCensor\Model\Project;
use PHPCensor\Service\BuildStatusService;
/**
* Unit tests for the ProjectService class.
*
* @author Dan Cryer <dan@block8.co.uk>
*/
class BuildStatusServiceTest extends \PHPUnit\Framework\TestCase
{
const BRANCH = 'master';
/** @var Project */
protected $project;
protected $timezone;
public function setUp()
{
$project = new Project();
$project->setId(3);
$project->setBranch(self::BRANCH);
$project->setTitle('Test');
$this->project = $project;
$this->timezone = date_default_timezone_get();
date_default_timezone_set('UTC');
}
public function tearDown()
{
date_default_timezone_set($this->timezone);
}
/**
* @param $configId
* @param bool $setProject
* @return Build
*/
protected function getBuild($configId, $setProject = true)
{
$config = [
'1' => [
'status' => Build::STATUS_RUNNING,
'id' => 77,
'finishDateTime' => null,
'startedDate' => '2014-10-25 21:20:02',
'previousBuild' => null,
],
'2' => [
'status' => Build::STATUS_RUNNING,
'id' => 78,
'finishDateTime' => null,
'startedDate' => '2014-10-25 21:20:02',
'previousBuild' => 4,
],
'3' => [
'status' => Build::STATUS_SUCCESS,
'id' => 7,
'finishDateTime' => '2014-10-25 21:50:02',
'startedDate' => '2014-10-25 21:20:02',
'previousBuild' => null,
],
'4' => [
'status' => Build::STATUS_FAILED,
'id' => 13,
'finishDateTime' => '2014-10-13 13:13:13',
'previousBuild' => null,
],
'5' => [
'status' => Build::STATUS_PENDING,
'id' => 1000,
'finishDateTime' => '2014-12-25 21:12:21',
'previousBuild' => 3,
]
];
$build = new Build();
$build->setId($config[$configId]['id']);
$build->setBranch(self::BRANCH);
$build->setStatus($config[$configId]['status']);
if ($config[$configId]['finishDateTime']) {
$build->setFinishDate(new \DateTime($config[$configId]['finishDateTime']));
}
if (!empty($config[$configId]['startedDate'])) {
$build->setStartDate(new \DateTime('2014-10-25 21:20:02'));
}
$project = $this->getProjectMock($config[$configId]['previousBuild'], $setProject);
$build->setProjectId($project->getId());
return $build;
}
/**
* @param null|int $prevBuildId
* @param bool $setProject
* @return Project
*/
protected function getProjectMock($prevBuildId = null, $setProject = true) {
$project = $this
->getMockBuilder('PHPCensor\Model\Project')
->setMethods(['getLatestBuild'])
->getMock();
$prevBuild = ($prevBuildId) ? $this->getBuild($prevBuildId, false) : null;
$project->expects($this->any())
->method('getLatestBuild')
->will($this->returnValue($prevBuild));
/* @var $project Project */
$project->setId(3);
$project->setBranch(self::BRANCH);
$project->setTitle('Test');
if ($setProject) {
$this->project = $project;
}
return $project;
}
/**
* @dataProvider finishedProvider
*
* @param int $buildConfigId
* @param array $expectedResult
*/
public function testFinished($buildConfigId, array $expectedResult)
{
$build = $this->getBuild($buildConfigId);
$service = new BuildStatusService(self::BRANCH, $this->project, $build);
$service->setUrl('http://php-censor.local/');
self::assertEquals($expectedResult, $service->toArray());
}
public function finishedProvider()
{
return [
'buildingStatus' => [
1,
[
'name' => 'Test / master',
'activity' => 'Building',
'lastBuildLabel' => '',
'lastBuildStatus' => '',
'lastBuildTime' => '',
'webUrl' => 'http://php-censor.local/build/view/77',
]
],
'buildingStatusWithPrev' => [
2,
[
'name' => 'Test / master',
'activity' => 'Building',
'lastBuildLabel' => 13,
'lastBuildStatus' => 'Failure',
'lastBuildTime' => '2014-10-13T13:13:13+0000',
'webUrl' => 'http://php-censor.local/build/view/78',
]
],
'successStatus' => [
3,
[
'name' => 'Test / master',
'activity' => 'Sleeping',
'lastBuildLabel' => 7,
'lastBuildStatus' => 'Success',
'lastBuildTime' => '2014-10-25T21:50:02+0000',
'webUrl' => 'http://php-censor.local/build/view/7',
]
],
'failureStatus' => [
4,
[
'name' => 'Test / master',
'activity' => 'Sleeping',
'lastBuildLabel' => 13,
'lastBuildStatus' => 'Failure',
'lastBuildTime' => '2014-10-13T13:13:13+0000',
'webUrl' => 'http://php-censor.local/build/view/13',
]
],
'pending' => [
5,
[
'name' => 'Test / master',
'activity' => 'Pending',
'lastBuildLabel' => 7,
'lastBuildStatus' => 'Success',
'lastBuildTime' => '2014-10-25T21:50:02+0000',
'webUrl' => 'http://php-censor.local/build/view/1000',
]
],
];
}
}

View file

@ -0,0 +1,120 @@
<?php
namespace Tests\PHPCensor\Service;
use PHPCensor\Model\Project;
use PHPCensor\Service\ProjectService;
/**
* Unit tests for the ProjectService class.
*
* @author Dan Cryer <dan@block8.co.uk>
*/
class ProjectServiceTest extends \PHPUnit\Framework\TestCase
{
/**
* @var ProjectService $testedService
*/
protected $testedService;
/**
* @var \ $mockProjectStore
*/
protected $mockProjectStore;
public function setUp()
{
$this->mockProjectStore = $this->getMockBuilder('PHPCensor\Store\ProjectStore')->getMock();
$this->mockProjectStore->expects($this->any())
->method('save')
->will($this->returnArgument(0));
$this->testedService = new ProjectService($this->mockProjectStore);
}
public function testExecute_CreateBasicProject()
{
$returnValue = $this->testedService->createProject('Test Project', 'github', 'block8/phpci', 0);
self::assertEquals('Test Project', $returnValue->getTitle());
self::assertEquals('github', $returnValue->getType());
self::assertEquals('block8/phpci', $returnValue->getReference());
self::assertEquals('master', $returnValue->getBranch());
}
public function testExecute_CreateProjectWithOptions()
{
$options = [
'ssh_private_key' => 'private',
'ssh_public_key' => 'public',
'allow_public_status' => 1,
'build_config' => 'config',
'branch' => 'testbranch',
];
$returnValue = $this->testedService->createProject('Test Project', 'github', 'block8/phpci', 0, $options);
self::assertEquals('private', $returnValue->getSshPrivateKey());
self::assertEquals('public', $returnValue->getSshPublicKey());
self::assertEquals('config', $returnValue->getBuildConfig());
self::assertEquals('testbranch', $returnValue->getBranch());
self::assertEquals(1, $returnValue->getAllowPublicStatus());
}
/**
* @link https://github.com/Block8/PHPCI/issues/484
*/
public function testExecute_CreateGitlabProjectWithoutPort()
{
$reference = 'git@gitlab.block8.net:block8/phpci.git';
$returnValue = $this->testedService->createProject('Gitlab', 'gitlab', $reference, 0);
self::assertEquals('git', $returnValue->getAccessInformation('user'));
self::assertEquals('gitlab.block8.net', $returnValue->getAccessInformation('domain'));
self::assertEquals('block8/phpci', $returnValue->getReference());
}
public function testExecute_UpdateExistingProject()
{
$project = new Project();
$project->setTitle('Before Title');
$project->setReference('Before Reference');
$project->setType('github');
$returnValue = $this->testedService->updateProject($project, 'After Title', 'bitbucket', 'After Reference');
self::assertEquals('After Title', $returnValue->getTitle());
self::assertEquals('After Reference', $returnValue->getReference());
self::assertEquals('bitbucket', $returnValue->getType());
}
public function testExecute_EmptyPublicStatus()
{
$project = new Project();
$project->setAllowPublicStatus(1);
$options = [
'ssh_private_key' => 'private',
'ssh_public_key' => 'public',
'build_config' => 'config',
];
$returnValue = $this->testedService->updateProject($project, 'Test Project', 'github', 'block8/phpci', $options);
self::assertEquals(0, $returnValue->getAllowPublicStatus());
}
public function testExecute_DeleteProject()
{
$store = $this->getMockBuilder('PHPCensor\Store\ProjectStore')->getMock();
$store->expects($this->once())
->method('delete')
->will($this->returnValue(true));
$service = new ProjectService($store);
$project = new Project();
self::assertEquals(true, $service->deleteProject($project));
}
}

View file

@ -0,0 +1,107 @@
<?php
namespace Tests\PHPCensor\Service;
use PHPCensor\Model\User;
use PHPCensor\Service\UserService;
/**
* Unit tests for the ProjectService class.
*
* @author Dan Cryer <dan@block8.co.uk>
*/
class UserServiceTest extends \PHPUnit\Framework\TestCase
{
/**
* @var UserService $testedService
*/
protected $testedService;
/**
* @var \ $mockBuildStore
*/
protected $mockUserStore;
public function setUp()
{
$this->mockUserStore = $this->getMockBuilder('PHPCensor\Store\UserStore')->getMock();
$this->mockUserStore->expects($this->any())
->method('save')
->will($this->returnArgument(0));
$this->testedService = new UserService($this->mockUserStore);
}
public function testExecute_CreateNonAdminUser()
{
$user = $this->testedService->createUser(
'Test',
'test@example.com',
'internal',
json_encode(['type' => 'internal']),
'testing',
false
);
self::assertEquals('Test', $user->getName());
self::assertEquals('test@example.com', $user->getEmail());
self::assertEquals(0, $user->getIsAdmin());
self::assertTrue(password_verify('testing', $user->getHash()));
}
public function testExecute_CreateAdminUser()
{
$user = $this->testedService->createUser(
'Test',
'test@example.com',
'internal',
json_encode(['type' => 'internal']),
'testing',
true
);
self::assertEquals(1, $user->getIsAdmin());
}
public function testExecute_RevokeAdminStatus()
{
$user = new User();
$user->setEmail('test@example.com');
$user->setName('Test');
$user->setIsAdmin(1);
$user = $this->testedService->updateUser($user, 'Test', 'test@example.com', 'testing', 0);
self::assertEquals(0, $user->getIsAdmin());
}
public function testExecute_GrantAdminStatus()
{
$user = new User();
$user->setEmail('test@example.com');
$user->setName('Test');
$user->setIsAdmin(0);
$user = $this->testedService->updateUser($user, 'Test', 'test@example.com', 'testing', 1);
self::assertEquals(1, $user->getIsAdmin());
}
public function testExecute_ChangesPasswordIfNotEmpty()
{
$user = new User();
$user->setHash(password_hash('testing', PASSWORD_DEFAULT));
$user = $this->testedService->updateUser($user, 'Test', 'test@example.com', 'newpassword', 0);
self::assertFalse(password_verify('testing', $user->getHash()));
self::assertTrue(password_verify('newpassword', $user->getHash()));
}
public function testExecute_DoesNotChangePasswordIfEmpty()
{
$user = new User();
$user->setHash(password_hash('testing', PASSWORD_DEFAULT));
$user = $this->testedService->updateUser($user, 'Test', 'test@example.com', '', 0);
self::assertTrue(password_verify('testing', $user->getHash()));
}
}

268
tests/src/StoreMysqlTest.php Executable file
View file

@ -0,0 +1,268 @@
<?php
namespace Tests\PHPCensor;
use PHPCensor\Config;
use PHPCensor\Database;
use PHPCensor\Store\Factory;
use PHPCensor\Model\Project;
use PHPCensor\Model\ProjectGroup;
use PHPCensor\Store;
class WrongStore extends Store
{
protected $tableName = 'project_group';
protected $modelName = '\PHPCensor\Model\ProjectGroup';
public function getByPrimaryKey($key, $useConnection = 'read')
{
return null;
}
}
class StoreMysqlTest extends \PHPUnit_Extensions_Database_TestCase
{
/**
* @var \PHPUnit_Extensions_Database_DB_DefaultDatabaseConnection|null
*/
protected $connection = null;
/**
* @param string $name
* @param array $data
* @param string $dataName
*/
public function __construct($name = null, array $data = [], $dataName = '')
{
parent::__construct($name, $data, $dataName);
if (extension_loaded('mysqli')) {
if (null === $this->connection) {
try {
$pdo = new \PDO(
'mysql:host=localhost;dbname=' . MYSQL_DBNAME,
MYSQL_USER,
MYSQL_PASSWORD
);
$this->connection = $this->createDefaultDBConnection($pdo, MYSQL_DBNAME);
$this->connection->getConnection()->query('
CREATE TABLE IF NOT EXISTS `project_group` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL,
`create_date` datetime,
`user_id` int(11) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
');
} catch (\PDOException $ex) {
$this->connection = null;
}
}
} else {
$this->connection = null;
}
}
/**
* @return \PHPUnit_Extensions_Database_DB_IDatabaseConnection
*/
protected function getConnection()
{
if (null === $this->connection) {
$this->markTestSkipped('Test skipped because MySQL database/user/extension doesn`t exist.');
}
return $this->connection;
}
/**
* @return \PHPUnit_Extensions_Database_DataSet_IDataSet
*/
protected function getDataSet()
{
return $this->createArrayDataSet([
'project_group' => [[
'id' => 1,
'title' => 'group 1',
'create_date' => null,
'user_id' => 0,
], [
'id' => 2,
'title' => 'group 2',
'create_date' => null,
'user_id' => 0,
], [
'id' => 3,
'title' => 'group 3',
'create_date' => null,
'user_id' => 1,
], [
'id' => 4,
'title' => 'group 4',
'create_date' => null,
'user_id' => 1,
], [
'id' => 5,
'title' => 'group 5',
'create_date' => '2018-01-01 01:01:00',
'user_id' => 2,
], [
'id' => 6,
'title' => 'group 6',
'create_date' => '2018-02-01 01:01:00',
'user_id' => 3,
], [
'id' => 7,
'title' => 'group 7',
'create_date' => '2018-03-01 01:01:00',
'user_id' => 4,
]],
]);
}
protected function setUp()
{
parent::setUp();
new Config([
'b8' => [
'database' => [
'servers' => [
'read' => [
['host' => 'localhost'],
],
'write' => [
['host' => 'localhost'],
],
],
'type' => Database::MYSQL_TYPE,
'name' => MYSQL_DBNAME,
'username' => MYSQL_USER,
'password' => MYSQL_PASSWORD,
],
],
]);
Database::reset();
}
/**
* @expectedException \RuntimeException
*/
public function testConstruct()
{
$store = new WrongStore();
}
public function testGetWhere()
{
$testStore = Factory::getStore('ProjectGroup');
$data = $testStore->getWhere([], 3, 1, ['id' => 'DESC']);
self::assertEquals(7, $data['count']);
self::assertEquals(3, count($data['items']));
self::assertEquals(6, $data['items'][0]->getId());
self::assertEquals(5, $data['items'][1]->getId());
self::assertEquals(4, $data['items'][2]->getId());
$data = $testStore->getWhere(['project_group.user_id' => 0], 100, 0, ['id' => 'ASC']);
self::assertEquals(2, $data['count']);
self::assertEquals(2, count($data['items']));
self::assertEquals(1, $data['items'][0]->getId());
self::assertEquals(2, $data['items'][1]->getId());
try {
$data = $testStore->getWhere(['' => 0], 100, 0, ['id' => 'ASC']);
} catch (\InvalidArgumentException $e) {
self::assertEquals('You cannot have an empty field name.', $e->getMessage());
}
try {
$data = $testStore->getWhere([], '; SELECT', 0, ['id' => 'ASC']);
} catch (\PDOException $e) {
self::assertInstanceOf('\PDOException', $e);
}
}
public function testSaveByInsert()
{
$testStore = Factory::getStore('ProjectGroup');
$model = new ProjectGroup();
$model->setTitle('group 8');
$testStore->save($model);
$newModel = $testStore->getByPrimaryKey(8);
self::assertEquals(8, $newModel->getId());
self::assertEquals('group 8', $newModel->getTitle());
}
public function testSaveByUpdate()
{
$testStore = Factory::getStore('ProjectGroup');
$model = $testStore->getByPrimaryKey(7);
$model->setTitle('group 100');
$testStore->save($model);
$newModel = $testStore->getByPrimaryKey(7);
self::assertEquals(7, $newModel->getId());
self::assertEquals('group 100', $newModel->getTitle());
// Without changes
$model = $testStore->getByPrimaryKey(6);
$testStore->save($model);
$newModel = $testStore->getByPrimaryKey(6);
self::assertEquals(6, $newModel->getId());
self::assertEquals('group 6', $newModel->getTitle());
// Wrong Model
try {
$model = new Project();
$model->setId(1);
$testStore->save($model);
} catch (\InvalidArgumentException $e) {
self::assertEquals(
'PHPCensor\Model\Project is an invalid model type for this store.',
$e->getMessage()
);
}
}
public function testDelete()
{
$testStore = Factory::getStore('ProjectGroup');
$model = $testStore->getByPrimaryKey(5);
$testStore->delete($model);
$newModel = $testStore->getByPrimaryKey(5);
self::assertEquals(null, $newModel);
// Wrong Model
try {
$model = new Project();
$model->setId(1);
$testStore->delete($model);
} catch (\InvalidArgumentException $e) {
self::assertEquals(
'PHPCensor\Model\Project is an invalid model type for this store.',
$e->getMessage()
);
}
}
}

263
tests/src/StorePostgresqlTest.php Executable file
View file

@ -0,0 +1,263 @@
<?php
namespace Tests\PHPCensor;
use PHPCensor\Config;
use PHPCensor\Database;
use PHPCensor\Store\Factory;
use PHPCensor\Model\Project;
use PHPCensor\Model\ProjectGroup;
class StorePostgresqlTest extends \PHPUnit_Extensions_Database_TestCase
{
/**
* @var \PHPUnit_Extensions_Database_DB_DefaultDatabaseConnection|null
*/
protected $connection = null;
/**
* @param string $name
* @param array $data
* @param string $dataName
*/
public function __construct($name = null, array $data = [], $dataName = '')
{
parent::__construct($name, $data, $dataName);
if (extension_loaded('pgsql')) {
if (null === $this->connection) {
try {
$pdo = new \PDO(
'pgsql:host=localhost;dbname=' . POSTGRESQL_DBNAME,
POSTGRESQL_USER,
POSTGRESQL_PASSWORD
);
$this->connection = $this->createDefaultDBConnection($pdo, POSTGRESQL_DBNAME);
$this->connection->getConnection()->query('
CREATE TABLE IF NOT EXISTS "project_group" (
"id" SERIAL,
"title" character varying(100) NOT NULL,
"create_date" timestamp without time zone,
"user_id" integer NOT NULL DEFAULT 0,
PRIMARY KEY ("id")
)
');
} catch (\PDOException $ex) {
$this->connection = null;
}
}
} else {
$this->connection = null;
}
}
/**
* @return \PHPUnit_Extensions_Database_DB_IDatabaseConnection
*/
protected function getConnection()
{
if (null === $this->connection) {
$this->markTestSkipped('Test skipped because PostgreSQL database/user/extension doesn`t exist.');
}
return $this->connection;
}
/**
* @return \PHPUnit_Extensions_Database_DataSet_IDataSet
*/
protected function getDataSet()
{
return $this->createArrayDataSet([
'project_group' => [[
'id' => 1,
'title' => 'group 1',
'create_date' => null,
'user_id' => 0,
], [
'id' => 2,
'title' => 'group 2',
'create_date' => null,
'user_id' => 0,
], [
'id' => 3,
'title' => 'group 3',
'create_date' => null,
'user_id' => 1,
], [
'id' => 4,
'title' => 'group 4',
'create_date' => null,
'user_id' => 1,
], [
'id' => 5,
'title' => 'group 5',
'create_date' => '2018-01-01 01:01:00',
'user_id' => 2,
], [
'id' => 6,
'title' => 'group 6',
'create_date' => '2018-02-01 01:01:00',
'user_id' => 3,
], [
'id' => 7,
'title' => 'group 7',
'create_date' => '2018-03-01 01:01:00',
'user_id' => 4,
]],
]);
}
protected function setUp()
{
parent::setUp();
new Config([
'b8' => [
'database' => [
'servers' => [
'read' => [
['host' => 'localhost'],
],
'write' => [
['host' => 'localhost'],
],
],
'type' => Database::POSTGRESQL_TYPE,
'name' => POSTGRESQL_DBNAME,
'username' => POSTGRESQL_USER,
'password' => POSTGRESQL_PASSWORD,
],
],
]);
Database::reset();
}
/**
* @expectedException \RuntimeException
*/
public function testConstruct()
{
$store = new WrongStore();
}
public function testGetWhere()
{
$testStore = Factory::getStore('ProjectGroup');
$data = $testStore->getWhere([], 3, 1, ['id' => 'DESC']);
self::assertEquals(7, $data['count']);
self::assertEquals(3, count($data['items']));
self::assertEquals(6, $data['items'][0]->getId());
self::assertEquals(5, $data['items'][1]->getId());
self::assertEquals(4, $data['items'][2]->getId());
$data = $testStore->getWhere(['project_group.user_id' => 0], 100, 0, ['id' => 'ASC']);
self::assertEquals(2, $data['count']);
self::assertEquals(2, count($data['items']));
self::assertEquals(1, $data['items'][0]->getId());
self::assertEquals(2, $data['items'][1]->getId());
try {
$data = $testStore->getWhere(['' => 0], 100, 0, ['id' => 'ASC']);
} catch (\InvalidArgumentException $e) {
self::assertEquals('You cannot have an empty field name.', $e->getMessage());
}
try {
$data = $testStore->getWhere([], '; SELECT', 0, ['id' => 'ASC']);
} catch (\PDOException $e) {
self::assertInstanceOf('\PDOException', $e);
}
}
public function testSaveByInsert()
{
$this->connection->getConnection()->query('
ALTER SEQUENCE "project_group_id_seq" RESTART WITH 8;
');
$testStore = Factory::getStore('ProjectGroup');
$model = new ProjectGroup();
$model->setTitle('group 8');
$testStore->save($model);
$newModel = $testStore->getByPrimaryKey(8);
self::assertEquals(8, $newModel->getId());
self::assertEquals('group 8', $newModel->getTitle());
}
public function testSaveByUpdate()
{
$this->connection->getConnection()->query('
ALTER SEQUENCE "project_group_id_seq" RESTART WITH 8;
');
$testStore = Factory::getStore('ProjectGroup');
$model = $testStore->getByPrimaryKey(7);
$model->setTitle('group 100');
$testStore->save($model);
$newModel = $testStore->getByPrimaryKey(7);
self::assertEquals(7, $newModel->getId());
self::assertEquals('group 100', $newModel->getTitle());
// Without changes
$model = $testStore->getByPrimaryKey(6);
$testStore->save($model);
$newModel = $testStore->getByPrimaryKey(6);
self::assertEquals(6, $newModel->getId());
self::assertEquals('group 6', $newModel->getTitle());
// Wrong Model
try {
$model = new Project();
$model->setId(1);
$testStore->save($model);
} catch (\InvalidArgumentException $e) {
self::assertEquals(
'PHPCensor\Model\Project is an invalid model type for this store.',
$e->getMessage()
);
}
}
public function testDelete()
{
$testStore = Factory::getStore('ProjectGroup');
$model = $testStore->getByPrimaryKey(5);
$testStore->delete($model);
$newModel = $testStore->getByPrimaryKey(5);
self::assertEquals(null, $newModel);
// Wrong Model
try {
$model = new Project();
$model->setId(1);
$testStore->delete($model);
} catch (\InvalidArgumentException $e) {
self::assertEquals(
'PHPCensor\Model\Project is an invalid model type for this store.',
$e->getMessage()
);
}
}
}

39
tests/src/ViewTest.php Executable file
View file

@ -0,0 +1,39 @@
<?php
namespace Tests\PHPCensor;
use PHPCensor\View;
class ViewTest extends \PHPUnit\Framework\TestCase
{
public function testSimpleView()
{
$view = new View('simple', ROOT_DIR . 'tests/data/View/');
self::assertTrue($view->render() == 'Hello');
}
/**
* @expectedException \Exception
*/
public function testInvalidView()
{
new View('dogs', ROOT_DIR . 'tests/data/View/');
}
public function testViewVars()
{
$view = new View('vars', ROOT_DIR . 'tests/data/View/');
$view->who = 'World';
self::assertTrue(isset($view->who));
self::assertFalse(isset($view->what));
self::assertTrue($view->render() == 'Hello World');
}
public function testUserViewVars()
{
$view = new View('{@content}');
$view->content = 'World';
self::assertTrue($view->render() == 'World');
}
}