Merge pull request #492 from Block8/dc/services-layer

Add a services layer to PHPCI for better unit testability
This commit is contained in:
Dan Cryer 2014-07-25 09:11:06 +01:00
commit 8bfffc7e9a
19 changed files with 1037 additions and 145 deletions

View file

@ -9,6 +9,7 @@
namespace PHPCI\Command;
use PHPCI\Service\UserService;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
@ -37,7 +38,9 @@ class CreateAdminCommand extends Command
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$userStore = Factory::getStore('User');
$userService = new UserService($userStore);
require(PHPCI_DIR . 'bootstrap.php');
// Try to create a user account:
@ -51,15 +54,7 @@ class CreateAdminCommand extends Command
$adminName = $this->ask('Admin name: ');
try {
$user = new \PHPCI\Model\User();
$user->setEmail($adminEmail);
$user->setName($adminName);
$user->setIsAdmin(1);
$user->setHash(password_hash($adminPass, PASSWORD_DEFAULT));
$store = \b8\Store\Factory::getStore('User');
$store->save($user);
$userService->createUser($adminName, $adminEmail, $adminPass, 1);
print 'User account created!' . PHP_EOL;
} catch (\Exception $ex) {
print 'There was a problem creating your account. :(' . PHP_EOL;

View file

@ -236,16 +236,11 @@ class InstallCommand extends Command
$adminName = $dialog->ask($output, 'Enter your name: ');
try {
$user = new User();
$user->setEmail($adminEmail);
$user->setName($adminName);
$user->setIsAdmin(1);
$user->setHash(password_hash($adminPass, PASSWORD_DEFAULT));
$this->reloadConfig();
$store = Factory::getStore('User');
$store->save($user);
$userStore = Factory::getStore('User');
$userService = new UserService($userStore);
$userService->createUser($adminName, $adminEmail, $adminPass, 1);
$output->writeln('<info>User account created!</info>');
} catch (\Exception $ex) {

View file

@ -13,6 +13,7 @@ use b8;
use b8\Exception\HttpException\NotFoundException;
use PHPCI\BuildFactory;
use PHPCI\Model\Build;
use PHPCI\Service\BuildService;
/**
* Build Controller - Allows users to run and view builds.
@ -26,10 +27,16 @@ class BuildController extends \PHPCI\Controller
* @var \PHPCI\Store\BuildStore
*/
protected $buildStore;
/**
* @var \PHPCI\Service\BuildService
*/
protected $buildService;
public function init()
{
$this->buildStore = b8\Store\Factory::getStore('Build');
$this->buildStore = b8\Store\Factory::getStore('Build');
$this->buildService = new BuildService($this->buildStore);
}
/**
@ -123,17 +130,7 @@ class BuildController extends \PHPCI\Controller
throw new NotFoundException('Build with ID: ' . $buildId . ' does not exist.');
}
$build = new Build();
$build->setProjectId($copy->getProjectId());
$build->setCommitId($copy->getCommitId());
$build->setStatus(Build::STATUS_NEW);
$build->setBranch($copy->getBranch());
$build->setCreated(new \DateTime());
$build->setCommitterEmail($copy->getCommitterEmail());
$build->setCommitMessage($copy->getCommitMessage());
$build->setExtra(json_encode($copy->getExtra()));
$build = $this->buildStore->save($build);
$build = $this->buildService->createDuplicateBuild($copy);
header('Location: '.PHPCI_URL.'build/view/' . $build->getId());
exit;
@ -154,7 +151,7 @@ class BuildController extends \PHPCI\Controller
throw new NotFoundException('Build with ID: ' . $buildId . ' does not exist.');
}
$this->buildStore->delete($build);
$this->buildService->delete($build);
header('Location: '.PHPCI_URL.'project/view/' . $build->getProjectId());
exit;

View file

@ -20,6 +20,8 @@ use PHPCI\Helper\Github;
use PHPCI\Helper\SshKey;
use PHPCI\Model\Build;
use PHPCI\Model\Project;
use PHPCI\Service\BuildService;
use PHPCI\Service\ProjectService;
/**
* Project Controller - Allows users to create, edit and view projects.
@ -29,20 +31,32 @@ use PHPCI\Model\Project;
*/
class ProjectController extends \PHPCI\Controller
{
/**
* @var \PHPCI\Store\ProjectStore
*/
protected $projectStore;
/**
* @var \PHPCI\Service\ProjectService
*/
protected $projectService;
/**
* @var \PHPCI\Store\BuildStore
*/
protected $buildStore;
/**
* @var \PHPCI\Store\ProjectStore
* @var \PHPCI\Service\BuildService
*/
protected $projectStore;
protected $buildService;
public function init()
{
$this->buildStore = Store\Factory::getStore('Build');
$this->projectStore = Store\Factory::getStore('Project');
$this->projectService = new ProjectService($this->projectStore);
$this->buildService = new BuildService($this->buildStore);
}
/**
@ -88,15 +102,7 @@ class ProjectController extends \PHPCI\Controller
throw new NotFoundException('Project with id: ' . $projectId . ' not found');
}
$build = new Build();
$build->setProjectId($projectId);
$build->setCommitId('Manual');
$build->setStatus(Build::STATUS_NEW);
$build->setBranch($project->getBranch());
$build->setCreated(new \DateTime());
$build->setCommitterEmail($_SESSION['user']->getEmail());
$build = $this->buildStore->save($build);
$build = $this->buildService->createBuild($project, null, null, $_SESSION['user']->getEmail());
header('Location: '.PHPCI_URL.'build/view/' . $build->getId());
exit;
@ -112,7 +118,7 @@ class ProjectController extends \PHPCI\Controller
}
$project = $this->projectStore->getById($projectId);
$this->projectStore->delete($project);
$this->projectService->delete($project);
header('Location: '.PHPCI_URL);
exit;
@ -179,35 +185,23 @@ class ProjectController extends \PHPCI\Controller
return $view->render();
} else {
return $this->addProject($form);
$title = $this->getParam('title', 'New Project');
$reference = $this->getParam('reference', null);
$type = $this->getParam('type', null);
$options = array(
'ssh_private_key' => $this->getParam('key', null),
'ssh_public_key' => $this->getParam('pubkey', null),
'build_config' => $this->getParam('build_config', null),
'allow_public_status' => $this->getParam('allow_public_status', 0),
);
$project = $this->projectService->createProject($title, $type, $reference, $options);
header('Location: '.PHPCI_URL.'project/view/' . $project->getId());
die;
}
}
protected function addProject(Form $form)
{
$values = $form->getValues();
$matches = array();
if ($values['type'] == "gitlab" && preg_match('`^(.*)@(.*):(.*)/(.*)\.git`', $values['reference'], $matches)) {
$info = array();
$info['user'] = $matches[1];
$info['domain'] = $matches[2];
$values['access_information'] = serialize($info);
$values['reference'] = $matches[3]."/".$matches[4];
}
$values['ssh_private_key'] = $values['key'];
$values['ssh_public_key'] = $values['pubkey'];
$project = new Project();
$project->setValues($values);
$project = $this->projectStore->save($project);
header('Location: '.PHPCI_URL.'project/view/' . $project->getId());
die;
}
/**
* Edit a project. Handles both the form and processing.
*/
@ -252,21 +246,18 @@ class ProjectController extends \PHPCI\Controller
return $view->render();
}
$values = $form->getValues();
$values['ssh_private_key'] = $values['key'];
$values['ssh_public_key'] = $values['pubkey'];
$title = $this->getParam('title', 'New Project');
$reference = $this->getParam('reference', null);
$type = $this->getParam('type', null);
if ($values['type'] == "gitlab") {
preg_match('`^(.*)@(.*):(.*)/(.*)\.git`', $values['reference'], $matches);
$info = array();
$info["user"] = $matches[1];
$info["domain"] = $matches[2];
$values['access_information'] = serialize($info);
$values['reference'] = $matches[3] . "/" . $matches[4];
}
$options = array(
'ssh_private_key' => $this->getParam('key', null),
'ssh_public_key' => $this->getParam('pubkey', null),
'build_config' => $this->getParam('build_config', null),
'allow_public_status' => $this->getParam('allow_public_status', 0),
);
$project->setValues($values);
$project = $this->projectStore->save($project);
$project = $this->projectService->updateProject($project, $title, $type, $reference, $options);
header('Location: '.PHPCI_URL.'project/view/' . $project->getId());
die;
@ -337,7 +328,7 @@ class ProjectController extends \PHPCI\Controller
$field = Form\Element\Checkbox::create('allow_public_status', $label, false);
$field->setContainerClass('form-group');
$field->setCheckedValue(1);
$field->setValue(1);
$field->setValue(0);
$form->addField($field);
$field = new Form\Element\Submit();

View file

@ -15,6 +15,7 @@ use b8\Exception\HttpException\NotFoundException;
use b8\Form;
use PHPCI\Controller;
use PHPCI\Model\User;
use PHPCI\Service\UserService;
/**
* User Controller - Allows an administrator to view, add, edit and delete users.
@ -29,9 +30,15 @@ class UserController extends Controller
*/
protected $userStore;
/**
* @var \PHPCI\Service\UserService
*/
protected $userService;
public function init()
{
$this->userStore = b8\Store\Factory::getStore('User');
$this->userService = new UserService($this->userStore);
}
/**
@ -53,16 +60,11 @@ class UserController extends Controller
$values = $user->getDataArray();
if ($this->request->getMethod() == 'POST') {
$values = $this->getParams();
$name = $this->getParam('name', null);
$email = $this->getParam('email', null);
$password = $this->getParam('password', null);
if (!empty($values['password'])) {
$values['hash'] = password_hash($values['password'], PASSWORD_DEFAULT);
}
$this->view->updated = true;
$user->setValues($values);
$_SESSION['user'] = $this->userStore->save($user);
$_SESSION['user'] = $this->userService->updateUser($name, $email, $password);
}
$form = new Form();
@ -132,13 +134,13 @@ class UserController extends Controller
return $view->render();
}
$values = $form->getValues();
$values['hash'] = password_hash($values['password'], PASSWORD_DEFAULT);
$user = new User();
$user->setValues($values);
$name = $this->getParam('name', null);
$email = $this->getParam('email', null);
$password = $this->getParam('password', null);
$isAdmin = (int)$this->getParam('is_admin', 0);
$user = $this->userStore->save($user);
$this->userService->createUser($name, $email, $password, $isAdmin);
header('Location: '.PHPCI_URL.'user');
die;
@ -172,18 +174,12 @@ class UserController extends Controller
return $view->render();
}
if (!empty($values['password'])) {
$values['hash'] = password_hash($values['password'], PASSWORD_DEFAULT);
}
$name = $this->getParam('name', null);
$email = $this->getParam('email', null);
$password = $this->getParam('password', null);
$isAdmin = (int)$this->getParam('is_admin', 0);
$user->setValues($values);
$isAdmin = $this->getParam('is_admin');
if (empty($isAdmin)) {
$user->setIsAdmin(0);
}
$this->userStore->save($user);
$this->userService->updateUser($user, $name, $email, $password, $isAdmin);
header('Location: '.PHPCI_URL.'user');
die;
@ -258,7 +254,7 @@ class UserController extends Controller
throw new NotFoundException('User with ID: ' . $userId . ' does not exist.');
}
$this->userStore->delete($user);
$this->userService->delete($user);
header('Location: '.PHPCI_URL.'user');
die;

View file

@ -13,6 +13,7 @@ use b8;
use b8\Store;
use PHPCI\BuildFactory;
use PHPCI\Model\Build;
use PHPCI\Service\BuildService;
/**
* Webhook Controller - Processes webhook pings from BitBucket, Github, Gitlab, etc.
@ -29,9 +30,21 @@ class WebhookController extends \PHPCI\Controller
*/
protected $buildStore;
/**
* @var \PHPCI\Store\ProjectStore
*/
protected $projectStore;
/**
* @var \PHPCI\Service\BuildService
*/
protected $buildService;
public function init()
{
$this->buildStore = Store\Factory::getStore('Build');
$this->projectStore = Store\Factory::getStore('Project');
$this->buildService = new BuildService($this->buildStore);
}
/**
@ -238,22 +251,15 @@ class WebhookController extends \PHPCI\Controller
return true;
}
// If not, create a new build job for it:
$build = new Build();
$build->setProjectId($projectId);
$build->setCommitId($commitId);
$build->setStatus(Build::STATUS_NEW);
$build->setLog('');
$build->setCreated(new \DateTime());
$build->setBranch($branch);
$build->setCommitterEmail($committer);
$build->setCommitMessage($commitMessage);
$project = $this->projectStore->getById($projectId);
if (!is_null($extra)) {
$build->setExtra(json_encode($extra));
if (empty($project)) {
throw new \Exception('Project does not exist:' . $projectId);
}
$build = BuildFactory::getBuild($this->buildStore->save($build));
// If not, create a new build job for it:
$build = $this->buildService->createBuild($project, $commitId, $branch, $committer, $commitMessage, $extra);
$build = BuildFactory::getBuild($build);
// Send a status postback if the build type provides one:
$build->sendStatusPostback();

View file

@ -36,6 +36,7 @@ class ProjectBase extends Model
'id' => null,
'title' => null,
'reference' => null,
'branch' => null,
'ssh_private_key' => null,
'ssh_public_key' => null,
'type' => null,
@ -200,17 +201,15 @@ class ProjectBase extends Model
}
/**
* Get the value of Branch / branch.
*
* @return string
*/
* Get the value of Branch / branch.
*
* @return string
*/
public function getBranch()
{
if (empty($this->data['branch'])) {
return $this->getType() === 'hg' ? 'default' : 'master';
} else {
return $this->data['branch'];
}
$rtn = $this->data['branch'];
return $rtn;
}
/**
@ -365,6 +364,7 @@ class ProjectBase extends Model
*/
public function setBranch($value)
{
$this->_validateNotNull('Branch', $value);
$this->_validateString('Branch', $value);
if ($this->data['branch'] === $value) {

View file

@ -38,15 +38,6 @@ class Build extends BuildBase
return '#';
}
/**
* @return string
*/
public function getProjectTitle()
{
$project = $this->getProject();
return $project ? $project->getTitle() : "";
}
/**
* Get link to branch from another source (i.e. Github)
*/
@ -55,6 +46,11 @@ class Build extends BuildBase
return '#';
}
public function getFileLinkTemplate()
{
return null;
}
/**
* Send status updates to any relevant third parties (i.e. Github)
*/
@ -63,6 +59,15 @@ class Build extends BuildBase
return;
}
/**
* @return string
*/
public function getProjectTitle()
{
$project = $this->getProject();
return $project ? $project->getTitle() : "";
}
/**
* Store build metadata
*/
@ -160,11 +165,6 @@ class Build extends BuildBase
return $config;
}
public function getFileLinkTemplate()
{
return null;
}
public function getExtra($key = null)
{
$data = json_decode($this->data['extra'], true);

View file

@ -58,4 +58,18 @@ class Project extends ProjectBase
return $rtn;
}
/**
* Get the value of Branch / branch.
*
* @return string
*/
public function getBranch()
{
if (empty($this->data['branch'])) {
return $this->getType() === 'hg' ? 'default' : 'master';
} else {
return $this->data['branch'];
}
}
}

View file

@ -0,0 +1,111 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2014, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link https://www.phptesting.org/
*/
namespace PHPCI\Service;
use PHPCI\Model\Build;
use PHPCI\Model\Project;
use PHPCI\Store\BuildStore;
class BuildService
{
/**
* @var \PHPCI\Store\BuildStore
*/
protected $buildStore;
/**
* @param BuildStore $buildStore
*/
public function __construct(BuildStore $buildStore)
{
$this->buildStore = $buildStore;
}
/**
* @param Project $project
* @param string|null $commitId
* @param string|null $branch
* @param string|null $committerEmail
* @param string|null $commitMessage
* @param string|null $extra
* @return \PHPCI\Model\Build
*/
public function createBuild(
Project $project,
$commitId = null,
$branch = null,
$committerEmail = null,
$commitMessage = null,
$extra = null
) {
$build = new Build();
$build->setCreated(new \DateTime());
$build->setProject($project);
$build->setStatus(0);
if (!is_null($commitId)) {
$build->setCommitId($commitId);
} else {
$build->setCommitId('Manual');
}
if (!is_null($branch)) {
$build->setBranch($branch);
} else {
$build->setBranch($project->getBranch());
}
if (!is_null($committerEmail)) {
$build->setCommitterEmail($committerEmail);
}
if (!is_null($commitMessage)) {
$build->setCommitMessage($commitMessage);
}
if (!is_null($extra)) {
$build->setExtra(json_encode($extra));
}
return $this->buildStore->save($build);
}
/**
* @param Build $copyFrom
* @return \PHPCI\Model\Build
*/
public function createDuplicateBuild(Build $copyFrom)
{
$data = $copyFrom->getDataArray();
// Clean up unwanted properties from the original build:
unset($data['id']);
unset($data['status']);
unset($data['log']);
unset($data['started']);
unset($data['finished']);
$build = new Build();
$build->setValues($data);
$build->setCreated(new \DateTime());
return $this->buildStore->save($build);
}
/**
* Delete a given build.
* @param Build $build
* @return bool
*/
public function deleteBuild(Build $build)
{
return $this->buildStore->delete($build);
}
}

View file

@ -0,0 +1,120 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2014, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link https://www.phptesting.org/
*/
namespace PHPCI\Service;
use PHPCI\Model\Project;
use PHPCI\Store\ProjectStore;
class ProjectService
{
/**
* @var \PHPCI\Store\ProjectStore
*/
protected $projectStore;
/**
* @param ProjectStore $projectStore
*/
public function __construct(ProjectStore $projectStore)
{
$this->projectStore = $projectStore;
}
/**
* Create a new project model and use the project store to save it.
* @param string $title
* @param string $type
* @param string $reference
* @param array $options
* @return \PHPCI\Model\Project
*/
public function createProject($title, $type, $reference, $options = array())
{
// Create base project and use updateProject() to set its properties:
$project = new Project();
return $this->updateProject($project, $title, $type, $reference, $options);
}
/**
* Update the properties of a given project.
* @param Project $project
* @param string $title
* @param string $type
* @param string $reference
* @param array $options
* @return \PHPCI\Model\Project
*/
public function updateProject(Project $project, $title, $type, $reference, $options = array())
{
// Set basic properties:
$project->setTitle($title);
$project->setType($type);
$project->setReference($reference);
$project->setAllowPublicStatus(0);
// Handle extra project options:
if (array_key_exists('ssh_private_key', $options)) {
$project->setSshPrivateKey($options['ssh_private_key']);
}
if (array_key_exists('ssh_public_key', $options)) {
$project->setSshPublicKey($options['ssh_public_key']);
}
if (array_key_exists('build_config', $options)) {
$project->setBuildConfig($options['build_config']);
}
if (array_key_exists('allow_public_status', $options)) {
$project->setAllowPublicStatus((int)$options['allow_public_status']);
}
if (array_key_exists('branch', $options)) {
$project->setBranch($options['branch']);
}
// Allow certain project types to set access information:
$this->processAccessInformation($project);
// Save and return the project:
return $this->projectStore->save($project);
}
/**
* Delete a given project.
* @param Project $project
* @return bool
*/
public function deleteProject(Project $project)
{
return $this->projectStore->delete($project);
}
/**
* In circumstances where it is necessary, populate access information based on other project properties.
* @see ProjectService::createProject()
* @param Project $project
*/
protected function processAccessInformation(Project &$project)
{
$matches = array();
$reference = $project->getReference();
if ($project->getType() == 'gitlab' && preg_match('`^(.*)@(.*):(.*)/(.*)\.git`', $reference, $matches)) {
$info = array();
$info['user'] = $matches[1];
$info['domain'] = $matches[2];
/** @todo At a later date, we need to find a way to replace this serialized data with JSON */
$project->setAccessInformation(serialize($info));
$project->setReference($matches[3] . '/' . $matches[4]);
}
}
}

View file

@ -0,0 +1,61 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2014, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link https://www.phptesting.org/
*/
namespace PHPCI\Service;
use PHPCI\Model\User;
use PHPCI\Store\UserStore;
class UserService
{
/**
* @var \PHPCI\Store\UserStore
*/
protected $store;
/**
* @param UserStore $store
*/
public function __construct(UserStore $store)
{
$this->store = $store;
}
public function createUser($name, $emailAddress, $password, $isAdmin = false)
{
$user = new User();
$user->setName($name);
$user->setEmail($emailAddress);
$user->setHash(password_hash($password, PASSWORD_DEFAULT));
$user->setIsAdmin(($isAdmin ? 1 : 0));
return $this->store->save($user);
}
public function updateUser(User $user, $name, $emailAddress, $password = null, $isAdmin = null)
{
$user->setName($name);
$user->setEmail($emailAddress);
if (!empty($password)) {
$user->setHash(password_hash($password, PASSWORD_DEFAULT));
}
if (!is_null($isAdmin)) {
$user->setIsAdmin(($isAdmin ? 1 : 0));
}
return $this->store->save($user);
}
public function deleteUser(User $user)
{
return $this->store->delete($user);
}
}

View file

@ -0,0 +1,84 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2014, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link http://www.phptesting.org/
*/
namespace PHPCI\Model\Tests;
use PHPCI\Model\Build;
use PHPCI\Model;
/**
* Unit tests for the Build model class.
* @author Dan Cryer <dan@block8.co.uk>
*/
class BuildTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestIsAValidModel()
{
$build = new Build();
$this->assertTrue($build instanceof \b8\Model);
$this->assertTrue($build instanceof Model);
$this->assertTrue($build instanceof Model\Base\BuildBase);
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestBaseBuildDefaults()
{
$build = new Build();
$this->assertEquals('#', $build->getCommitLink());
$this->assertEquals('#', $build->getBranchLink());
$this->assertEquals(null, $build->getFileLinkTemplate());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestIsSuccessful()
{
$build = new Build();
$build->setStatus(Build::STATUS_NEW);
$this->assertFalse($build->isSuccessful());
$build->setStatus(Build::STATUS_RUNNING);
$this->assertFalse($build->isSuccessful());
$build->setStatus(Build::STATUS_FAILED);
$this->assertFalse($build->isSuccessful());
$build->setStatus(Build::STATUS_SUCCESS);
$this->assertTrue($build->isSuccessful());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestBuildExtra()
{
$info = array(
'item1' => 'Item One',
'item2' => 2,
);
$build = new Build();
$build->setExtra(json_encode($info));
$this->assertEquals('Item One', $build->getExtra('item1'));
$this->assertEquals(2, $build->getExtra('item2'));
$this->assertNull($build->getExtra('item3'));
$this->assertEquals($info, $build->getExtra());
}
}

View file

@ -0,0 +1,109 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2014, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link http://www.phptesting.org/
*/
namespace PHPCI\Model\Tests;
use PHPCI\Model\Project;
use PHPCI\Model;
/**
* Unit tests for the Project model class.
* @author Dan Cryer <dan@block8.co.uk>
*/
class ProjectTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestIsAValidModel()
{
$project = new Project();
$this->assertTrue($project instanceof \b8\Model);
$this->assertTrue($project instanceof Model);
$this->assertTrue($project instanceof Model\Base\ProjectBase);
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestGitDefaultBranch()
{
$project = new Project();
$project->setType('git');
$this->assertEquals('master', $project->getBranch());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestGithubDefaultBranch()
{
$project = new Project();
$project->setType('github');
$this->assertEquals('master', $project->getBranch());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestGitlabDefaultBranch()
{
$project = new Project();
$project->setType('gitlab');
$this->assertEquals('master', $project->getBranch());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestBitbucketDefaultBranch()
{
$project = new Project();
$project->setType('bitbucket');
$this->assertEquals('master', $project->getBranch());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestMercurialDefaultBranch()
{
$project = new Project();
$project->setType('hg');
$this->assertEquals('default', $project->getBranch());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestProjectAccessInformation()
{
$info = array(
'item1' => 'Item One',
'item2' => 2,
);
$project = new Project();
$project->setAccessInformation(serialize($info));
$this->assertEquals('Item One', $project->getAccessInformation('item1'));
$this->assertEquals(2, $project->getAccessInformation('item2'));
$this->assertNull($project->getAccessInformation('item3'));
$this->assertEquals($info, $project->getAccessInformation());
}
}

View file

@ -0,0 +1,148 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2014, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link http://www.phptesting.org/
*/
namespace PHPCI\Service\Tests;
use PHPCI\Model\Build;
use PHPCI\Model\Project;
use PHPCI\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;
public function setUp()
{
$this->mockBuildStore = $this->getMock('PHPCI\Store\BuildStore');
$this->mockBuildStore->expects($this->any())
->method('save')
->will($this->returnArgument(0));
$this->testedService = new BuildService($this->mockBuildStore);
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_CreateBasicBuild()
{
$project = new Project();
$project->setType('github');
$project->setId(101);
$returnValue = $this->testedService->createBuild($project);
$this->assertEquals(101, $returnValue->getProjectId());
$this->assertEquals(Build::STATUS_NEW, $returnValue->getStatus());
$this->assertNull($returnValue->getStarted());
$this->assertNull($returnValue->getFinished());
$this->assertNull($returnValue->getLog());
$this->assertNull($returnValue->getCommitMessage());
$this->assertNull($returnValue->getCommitterEmail());
$this->assertNull($returnValue->getExtra());
$this->assertEquals('master', $returnValue->getBranch());
$this->assertInstanceOf('DateTime', $returnValue->getCreated());
$this->assertEquals('Manual', $returnValue->getCommitId());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_CreateBuildWithOptions()
{
$project = new Project();
$project->setType('hg');
$project->setId(101);
$returnValue = $this->testedService->createBuild($project, '123', 'testbranch', 'test@example.com', 'test');
$this->assertEquals('testbranch', $returnValue->getBranch());
$this->assertEquals('123', $returnValue->getCommitId());
$this->assertEquals('test', $returnValue->getCommitMessage());
$this->assertEquals('test@example.com', $returnValue->getCommitterEmail());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_CreateBuildWithExtra()
{
$project = new Project();
$project->setType('bitbucket');
$project->setId(101);
$returnValue = $this->testedService->createBuild($project, null, null, null, null, array('item1' => 1001));
$this->assertEquals(1001, $returnValue->getExtra('item1'));
}
/**
* @covers PHPUnit::execute
*/
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->setStarted(new \DateTime());
$build->setFinished(new \DateTime());
$build->setCommitMessage('test');
$build->setCommitterEmail('test@example.com');
$build->setExtra(json_encode(array('item1' => 1001)));
$returnValue = $this->testedService->createDuplicateBuild($build);
$this->assertNotEquals($build->getId(), $returnValue->getId());
$this->assertEquals($build->getProjectId(), $returnValue->getProjectId());
$this->assertEquals($build->getCommitId(), $returnValue->getCommitId());
$this->assertNotEquals($build->getStatus(), $returnValue->getStatus());
$this->assertEquals(Build::STATUS_NEW, $returnValue->getStatus());
$this->assertNull($returnValue->getLog());
$this->assertEquals($build->getBranch(), $returnValue->getBranch());
$this->assertNotEquals($build->getCreated(), $returnValue->getCreated());
$this->assertNull($returnValue->getStarted());
$this->assertNull($returnValue->getFinished());
$this->assertEquals('test', $returnValue->getCommitMessage());
$this->assertEquals('test@example.com', $returnValue->getCommitterEmail());
$this->assertEquals($build->getExtra('item1'), $returnValue->getExtra('item1'));
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_DeleteBuild()
{
$store = $this->getMock('PHPCI\Store\BuildStore');
$store->expects($this->once())
->method('delete')
->will($this->returnValue(true));
$service = new BuildService($store);
$build = new Build();
$this->assertEquals(true, $service->deleteBuild($build));
}
}

View file

@ -0,0 +1,142 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2014, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link http://www.phptesting.org/
*/
namespace PHPCI\Service\Tests;
use PHPCI\Model\Project;
use PHPCI\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->getMock('PHPCI\Store\ProjectStore');
$this->mockProjectStore->expects($this->any())
->method('save')
->will($this->returnArgument(0));
$this->testedService = new ProjectService($this->mockProjectStore);
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_CreateBasicProject()
{
$returnValue = $this->testedService->createProject('Test Project', 'github', 'block8/phpci');
$this->assertEquals('Test Project', $returnValue->getTitle());
$this->assertEquals('github', $returnValue->getType());
$this->assertEquals('block8/phpci', $returnValue->getReference());
$this->assertEquals('master', $returnValue->getBranch());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_CreateProjectWithOptions()
{
$options = array(
'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', $options);
$this->assertEquals('private', $returnValue->getSshPrivateKey());
$this->assertEquals('public', $returnValue->getSshPublicKey());
$this->assertEquals('config', $returnValue->getBuildConfig());
$this->assertEquals('testbranch', $returnValue->getBranch());
$this->assertEquals(1, $returnValue->getAllowPublicStatus());
}
/**
* @link https://github.com/Block8/PHPCI/issues/484
* @covers PHPUnit::execute
*/
public function testExecute_CreateGitlabProjectWithoutPort()
{
$reference = 'git@gitlab.block8.net:block8/phpci.git';
$returnValue = $this->testedService->createProject('Gitlab', 'gitlab', $reference);
$this->assertEquals('git', $returnValue->getAccessInformation('user'));
$this->assertEquals('gitlab.block8.net', $returnValue->getAccessInformation('domain'));
$this->assertEquals('block8/phpci', $returnValue->getReference());
}
/**
* @covers PHPUnit::execute
*/
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');
$this->assertEquals('After Title', $returnValue->getTitle());
$this->assertEquals('After Reference', $returnValue->getReference());
$this->assertEquals('bitbucket', $returnValue->getType());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_EmptyPublicStatus()
{
$project = new Project();
$project->setAllowPublicStatus(1);
$options = array(
'ssh_private_key' => 'private',
'ssh_public_key' => 'public',
'build_config' => 'config',
);
$returnValue = $this->testedService->updateProject($project, 'Test Project', 'github', 'block8/phpci', $options);
$this->assertEquals(0, $returnValue->getAllowPublicStatus());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_DeleteProject()
{
$store = $this->getMock('PHPCI\Store\ProjectStore');
$store->expects($this->once())
->method('delete')
->will($this->returnValue(true));
$service = new ProjectService($store);
$project = new Project();
$this->assertEquals(true, $service->deleteProject($project));
}
}

View file

@ -0,0 +1,116 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2014, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link http://www.phptesting.org/
*/
namespace PHPCI\Service\Tests;
use PHPCI\Model\User;
use PHPCI\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->getMock('PHPCI\Store\UserStore');
$this->mockUserStore->expects($this->any())
->method('save')
->will($this->returnArgument(0));
$this->testedService = new UserService($this->mockUserStore);
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_CreateNonAdminUser()
{
$user = $this->testedService->createUser('Test', 'test@example.com', 'testing', 0);
$this->assertEquals('Test', $user->getName());
$this->assertEquals('test@example.com', $user->getEmail());
$this->assertEquals(0, $user->getIsAdmin());
$this->assertTrue(password_verify('testing', $user->getHash()));
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_CreateAdminUser()
{
$user = $this->testedService->createUser('Test', 'test@example.com', 'testing', 1);
$this->assertEquals(1, $user->getIsAdmin());
}
/**
* @covers PHPUnit::execute
*/
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);
$this->assertEquals(0, $user->getIsAdmin());
}
/**
* @covers PHPUnit::execute
*/
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);
$this->assertEquals(1, $user->getIsAdmin());
}
/**
* @covers PHPUnit::execute
*/
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);
$this->assertFalse(password_verify('testing', $user->getHash()));
$this->assertTrue(password_verify('newpassword', $user->getHash()));
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_DoesNotChangePasswordIfEmpty()
{
$user = new User();
$user->setHash(password_hash('testing', PASSWORD_DEFAULT));
$user = $this->testedService->updateUser($user, 'Test', 'test@example.com', '', 0);
$this->assertTrue(password_verify('testing', $user->getHash()));
}
}

View file

@ -6,6 +6,7 @@ build_settings:
- "PHPCI/Command" # PHPMD complains about un-used parameters, but they are required.
- "public/install.php" # PHPCS really doesn't like PHP mixed with HTML (and so it shouldn't)
- "PHPCI/Migrations" # Ignore the migrations directory, as both PHPMD and PHPCS can't cope with them.
- "PHPCI/Model/Base" # These files are auto-generated, and sometimes hit PHPMD complexity thresholds.
setup:
composer:

View file

@ -20,5 +20,11 @@
<testsuite name="PHPCI Plugin Test Suite">
<directory suffix="Test.php">./Tests/PHPCI/Plugin</directory>
</testsuite>
<testsuite name="PHPCI Model Test Suite">
<directory suffix="Test.php">./Tests/PHPCI/Model</directory>
</testsuite>
<testsuite name="PHPCI Service Test Suite">
<directory suffix="Test.php">./Tests/PHPCI/Service</directory>
</testsuite>
</testsuites>
</phpunit>