1
0
mirror of https://github.com/laravel/valet.git synced 2026-02-05 16:40:05 +01:00

progress refactoring

This commit is contained in:
Taylor Otwell
2016-05-07 22:10:32 -05:00
parent 9f4896399e
commit 354e1d4111
12 changed files with 901 additions and 159 deletions

View File

@@ -24,9 +24,15 @@
},
"require": {
"php": ">=5.5.9",
"illuminate/container": "~5.1",
"mnapoli/silly": "~1.0",
"symfony/process": "~2.7|~3.0",
"nategood/httpful": "~0.2"
"nategood/httpful": "~0.2",
"tightenco/collect": "^5.2"
},
"require-dev": {
"mockery/mockery": "0.9.*",
"phpunit/phpunit": "~5.0"
},
"bin": [
"valet"

View File

@@ -1,15 +1,45 @@
<?php
use Illuminate\Container\Container;
use Symfony\Component\Process\Process;
/**
* Define the ~/.valet path as a constant.
*/
define('VALET_HOME_PATH', $_SERVER['HOME'].'/.valet');
/**
* Simple global function to run commands.
* Output the given text to the console.
*
* @param string $output
* @return void
*/
function quietly($command)
function output($output)
{
(new Process($command))->run();
(new Symfony\Component\Console\Output\ConsoleOutput)->writeln($output);
}
/**
* Resolve the given class from the container.
*
* @param string $class
* @return mixed
*/
function resolve($class)
{
return Container::getInstance()->make($class);
}
/**
* Swap the given class implementation in the container.
*
* @param string $class
* @param mixed $instance
* @return void
*/
function swap($class, $instance)
{
Container::getInstance()->instance($class, $instance);
}
/**
@@ -40,43 +70,6 @@ function retry($retries, $fn, $sleep = 0)
}
}
/**
* Run the given command.
*
* @param string $command
* @param callable $onError
* @return string
*/
function run($command, callable $onError = null)
{
return run_as_root('sudo -u '.$_SERVER['SUDO_USER'].' '.$command, $onError);
}
/**
* Run the given command as root.
*
* @param string $command
* @param callable $onError
* @return string
*/
function run_as_root($command, callable $onError = null)
{
$onError = $onError ?: function () {};
$process = new Process($command);
$processOutput = '';
$process->run(function ($type, $line) use (&$processOutput) {
$processOutput .= $line;
});
if ($process->getExitCode() > 0) {
$onError($process->getExitCode(), $processOutput);
}
return $processOutput;
}
/**
* Verify that the script is currently running as "sudo".
*
@@ -88,3 +81,29 @@ function should_be_sudo()
throw new Exception('This command must be run with sudo.');
}
}
/**
* Tap the given value.
*
* @param mixed $value
* @param callable $callback
* @return mixed
*/
function tap($value, callable $callback)
{
$callback($value);
return $value;
}
/**
* Get the user
*/
function user()
{
if (! isset($_SERVER['SUDO_USER'])) {
return $_SERVER['USER'];
}
return $_SERVER['SUDO_USER'];
}

19
phpunit.xml Normal file
View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="Valet Test Suite">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
<php>
<env name="APP_ENV" value="testing"/>
</php>
</phpunit>

View File

@@ -3,18 +3,35 @@
namespace Valet;
use Exception;
use DomainException;
class Brew
{
var $cli;
var $files;
/**
* Create a new Brew instance.
*
* @param CommandLine $cli
* @param Filesystem $files
* @return void
*/
function __construct(CommandLine $cli, Filesystem $files)
{
$this->cli = $cli;
$this->files = $files;
}
/**
* Determine if the given formula is installed.
*
* @param string $formula
* @return bool
*/
public static function installed($formula)
function installed($formula)
{
return in_array($formula, explode(PHP_EOL, run('brew list | grep '.$formula)));
return in_array($formula, explode(PHP_EOL, $this->cli->run('brew list | grep '.$formula)));
}
/**
@@ -22,9 +39,9 @@ public static function installed($formula)
*
* @return bool
*/
public static function hasInstalledPhp()
function hasInstalledPhp()
{
return static::installed('php70') || static::installed('php56');
return $this->installed('php70') || $this->installed('php56');
}
/**
@@ -33,12 +50,12 @@ public static function hasInstalledPhp()
* @param dynamic[string] $formula
* @return void
*/
public static function tap($formulas)
function tap($formulas)
{
$formulas = is_array($formulas) ? $formulas : func_get_args();
foreach ($formulas as $formula) {
passthru('sudo -u '.$_SERVER['SUDO_USER'].' brew tap '.$formula);
$this->cli->passthru('sudo -u '.user().' brew tap '.$formula);
}
}
@@ -47,12 +64,12 @@ public static function tap($formulas)
*
* @param
*/
public static function restartService($services)
function restartService($services)
{
$services = is_array($services) ? $services : func_get_args();
foreach ($services as $service) {
quietly('sudo brew services restart '.$service);
$this->cli->quietly('sudo brew services restart '.$service);
}
}
@@ -61,12 +78,12 @@ public static function restartService($services)
*
* @param
*/
public static function stopService($services)
function stopService($services)
{
$services = is_array($services) ? $services : func_get_args();
foreach ($services as $service) {
quietly('sudo brew services stop '.$service);
$this->cli->quietly('sudo brew services stop '.$service);
}
}
@@ -75,20 +92,20 @@ public static function stopService($services)
*
* @return string
*/
public static function linkedPhp()
function linkedPhp()
{
if (! is_link('/usr/local/bin/php')) {
throw new Exception("Unable to determine linked PHP.");
if (! $this->files->isLink('/usr/local/bin/php')) {
throw new DomainException("Unable to determine linked PHP.");
}
$resolvedPath = readlink('/usr/local/bin/php');
$resolvedPath = $this->files->readLink('/usr/local/bin/php');
if (strpos($resolvedPath, 'php70') !== false) {
return 'php70';
} elseif (strpos($resolvedPath, 'php56') !== false) {
return 'php56';
} else {
throw new Exception("Unable to determine linked PHP.");
throw new DomainException("Unable to determine linked PHP.");
}
}
@@ -97,8 +114,8 @@ public static function linkedPhp()
*
* @return void
*/
public static function restartLinkedPhp()
function restartLinkedPhp()
{
return static::restartService(static::linkedPhp());
return $this->restartService($this->linkedPhp());
}
}

View File

@@ -4,37 +4,81 @@
class Caddy
{
var $cli;
var $files;
var $daemonPath = '/Library/LaunchDaemons/com.laravel.valetServer.plist';
/**
* Install the system launch daemon for the Node proxy.
* Create a new Brew instance.
*
* @param CommandLine $cli
* @param Filesystem $files
* @return void
*/
function __construct(CommandLine $cli, Filesystem $files)
{
$this->cli = $cli;
$this->files = $files;
}
/**
* Install the system launch daemon for the Caddy server.
*
* @return void
*/
public static function install()
function install()
{
file_put_contents(
VALET_HOME_PATH.'/Caddyfile',
str_replace('USER', $_SERVER['SUDO_USER'], file_get_contents(__DIR__.'/../stubs/Caddyfile'))
);
chown(VALET_HOME_PATH.'/Caddyfile', $_SERVER['SUDO_USER']);
if (! is_dir($caddyDirectory = VALET_HOME_PATH.'/Caddy')) {
mkdir($caddyDirectory, 0755);
chown($caddyDirectory, $_SERVER['SUDO_USER']);
$this->installCaddyFile();
$this->installCaddyDirectory();
$this->installCaddyDaemon();
}
touch($caddyDirectory.'/.keep');
/**
* Install the Caddyfile to the ~/.valet directory.
*
* This file serves as the main server configuration for Valet.
*
* @return void
*/
function installCaddyFile()
{
$this->files->putAsUser(
VALET_HOME_PATH.'/Caddyfile',
str_replace('USER', user(), $this->files->get(__DIR__.'/../stubs/Caddyfile'))
);
}
chown($caddyDirectory.'/.keep', $_SERVER['SUDO_USER']);
/**
* Install the Caddy configuration directory to the ~/.valet directory.
*
* This directory contains all site-specific Caddy definitions.
*
* @return void
*/
function installCaddyDirectory()
{
if (! $this->files->isDir($caddyDirectory = VALET_HOME_PATH.'/Caddy')) {
$this->files->mkdirAsUser($caddyDirectory);
}
$this->files->touchAsUser($caddyDirectory.'/.keep');
}
/**
* Install the Caddy daemon on a system level daemon.
*
* @return void
*/
function installCaddyDaemon()
{
$contents = str_replace(
'VALET_PATH', realpath(__DIR__.'/../'), file_get_contents(__DIR__.'/../stubs/daemon.plist')
'VALET_PATH', $this->files->realpath(__DIR__.'/../'),
$this->files->get(__DIR__.'/../stubs/daemon.plist')
);
$contents = str_replace('VALET_HOME_PATH', VALET_HOME_PATH, $contents);
file_put_contents('/Library/LaunchDaemons/com.laravel.valetServer.plist', $contents);
$this->files->put(
$this->daemonPath, str_replace('VALET_HOME_PATH', VALET_HOME_PATH, $contents)
);
}
/**
@@ -42,11 +86,11 @@ public static function install()
*
* @return void
*/
public static function restart()
function restart()
{
quietly('launchctl unload /Library/LaunchDaemons/com.laravel.valetServer.plist > /dev/null');
$this->cli->quietly('launchctl unload '.$this->daemonPath);
exec('launchctl load /Library/LaunchDaemons/com.laravel.valetServer.plist');
$this->cli->quietly('launchctl load '.$this->daemonPath);
}
/**
@@ -54,9 +98,9 @@ public static function restart()
*
* @return void
*/
public static function stop()
function stop()
{
quietly('launchctl unload /Library/LaunchDaemons/com.laravel.valetServer.plist > /dev/null');
$this->cli->quietly('launchctl unload '.$this->daemonPath);
}
/**
@@ -64,10 +108,10 @@ public static function stop()
*
* @return void
*/
public static function uninstall()
function uninstall()
{
static::stop();
$this->stop();
unlink('/Library/LaunchDaemons/com.laravel.valetServer.plist');
$this->files->unlink($this->daemonPath);
}
}

64
src/CommandLine.php Normal file
View File

@@ -0,0 +1,64 @@
<?php
namespace Valet;
use Symfony\Component\Process\Process;
class CommandLine
{
/**
* Simple global function to run commands.
*/
public function quietly($command)
{
(new Process($command))->run();
}
/**
* Pass the command to the command line and display the output.
*
* @param string $command
* @return void
*/
public function passthru($command)
{
passthru($command);
}
/**
* Run the given command.
*
* @param string $command
* @param callable $onError
* @return string
*/
public function run($command, callable $onError = null)
{
return $this->runAsRoot('sudo -u '.$_SERVER['SUDO_USER'].' '.$command, $onError);
}
/**
* Run the given command as root.
*
* @param string $command
* @param callable $onError
* @return string
*/
public function runAsRoot($command, callable $onError = null)
{
$onError = $onError ?: function () {};
$process = new Process($command);
$processOutput = '';
$process->run(function ($type, $line) use (&$processOutput) {
$processOutput .= $line;
});
if ($process->getExitCode() > 0) {
$onError($process->getExitCode(), $processOutput);
}
return $processOutput;
}
}

View File

@@ -4,33 +4,85 @@
class Configuration
{
var $files;
/**
* Create a new Valet configuration class instance.
*
* @param Filesystem $filesystem
* @return void
*/
function __construct(Filesystem $files)
{
$this->files = $files;
}
/**
* Install the Valet configuration file.
*
* @return void
*/
public static function install()
function install()
{
if (! is_dir($directory = VALET_HOME_PATH)) {
mkdir($directory, 0755);
$this->createConfigurationDirectory();
$this->createDriversDirectory();
$this->writeBaseConfiguration();
chown($directory, $_SERVER['SUDO_USER']);
$this->files->chown($this->path(), user());
}
if (! is_dir($driversDirectory = VALET_HOME_PATH.'/Drivers')) {
mkdir($driversDirectory, 0755);
copy(__DIR__.'/../stubs/SampleValetDriver.php', $driversDirectory.'/SampleValetDriver.php');
chown($driversDirectory.'/SampleValetDriver.php', $_SERVER['SUDO_USER']);
chown($driversDirectory, $_SERVER['SUDO_USER']);
/**
* Create the Valet configuration directory.
*
* @return void
*/
function createConfigurationDirectory()
{
if (! $this->files->isDir(VALET_HOME_PATH)) {
$this->files->mkdirAsUser(VALET_HOME_PATH);
}
}
if (! file_exists(static::path())) {
static::write(['domain' => 'dev', 'paths' => []]);
/**
* Create the Valet drivers directory.
*
* @return void
*/
function createDriversDirectory()
{
if ($this->files->isDir($driversDirectory = VALET_HOME_PATH.'/Drivers')) {
return;
}
chown(static::path(), $_SERVER['SUDO_USER']);
$this->files->mkdirAsUser($driversDirectory);
$this->files->putAsUser(
$driversDirectory.'/SampleValetDriver.php',
$this->files->get(__DIR__.'/../stubs/SampleValetDriver.php')
);
}
/**
* Write the base, initial configuration for Valet.
*/
function writeBaseConfiguration()
{
if (! $this->files->exists($this->path())) {
$this->write(['domain' => 'dev', 'paths' => []]);
}
}
/**
* Add the given path to the configuration.
*
* @param string $path
* @return array
*/
function addPath($path)
{
$this->write(tap($this->read(), function (&$config) use ($path) {
$config['paths'] = collect($config['paths'])->push($path)->unique()->all();
}));
}
/**
@@ -39,44 +91,13 @@ public static function install()
* @param string $path
* @return void
*/
public static function addPath($path)
function removePath($path)
{
$config = static::read();
$config['paths'] = array_unique(array_merge($config['paths'], [$path]));
static::write($config);
}
/**
* Add the given path to the configuration.
*
* @param string $path
* @return void
*/
public static function removePath($path)
{
$config = static::read();
foreach ($config['paths'] as $key => $value) {
if ($path === $value) {
unset($config['paths'][$key]);
}
}
$config['paths'] = array_unique(array_values($config['paths']));
static::write($config);
}
/**
* Get the configuration file path.
*
* @return string
*/
public static function path()
{
return VALET_HOME_PATH.'/config.json';
$this->write(tap($this->read(), function (&$config) use ($path) {
$config['paths'] = collect($config['paths'])->reject(function ($value) use ($path) {
return $value === $path;
})->values()->all();
}));
}
/**
@@ -84,23 +105,17 @@ public static function path()
*
* @return void
*/
public static function prune()
function prune()
{
if (! file_exists(static::path())) {
if (! $this->files->exists($this->path())) {
return;
}
$config = static::read();
foreach ($config['paths'] as $key => $path) {
if (! is_dir($path)) {
unset($config['paths'][$key]);
}
}
$config['paths'] = array_values($config['paths']);
static::write($config);
$this->write(tap($this->read(), function (&$config) {
$config['paths'] = collect($config['paths'])->filter(function ($path) {
return $this->files->isDir($path);
})->values()->all();
}));
}
/**
@@ -108,9 +123,9 @@ public static function prune()
*
* @return array
*/
public static function read()
function read()
{
return json_decode(file_get_contents(static::path()), true);
return json_decode($this->files->get($this->path()), true);
}
/**
@@ -120,15 +135,13 @@ public static function read()
* @param mixed $value
* @return array
*/
public static function updateKey($key, $value)
function updateKey($key, $value)
{
$config = static::read();
return tap($this->read(), function (&$config) use ($key, $value) {
$config[$key] = $value;
static::write($config);
return $config;
$this->write($config);
});
}
/**
@@ -137,8 +150,20 @@ public static function updateKey($key, $value)
* @param array $config
* @return void
*/
public static function write(array $config)
function write(array $config)
{
file_put_contents(static::path(), json_encode($config, JSON_PRETTY_PRINT).PHP_EOL);
$this->files->putAsUser($this->path(), json_encode(
$config, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES
).PHP_EOL);
}
/**
* Get the configuration file path.
*
* @return string
*/
function path()
{
return VALET_HOME_PATH.'/config.json';
}
}

190
src/Filesystem.php Normal file
View File

@@ -0,0 +1,190 @@
<?php
namespace Valet;
class Filesystem
{
/**
* Determine if the given path is a directory.
*
* @param string $path
* @return bool
*/
public function isDir($path)
{
return is_dir($path);
}
/**
* Create a directory.
*
* @param string $path
* @param string|null $owner
* @param int $mode
* @return void
*/
public function mkdir($path, $owner = null, $mode = 0755)
{
mkdir($path, $mode);
if ($owner) {
$this->chown($path, $owner);
}
}
/**
* Create a directory as the non-root user.
*
* @param string $path
* @param int $mode
* @return void
*/
public function mkdirAsUser($path, $mode = 0755)
{
return $this->mkdir($path, user(), $mode);
}
/**
* Touch the given path.
*
* @param string $path
* @param string|null $owner
* @return void
*/
public function touch($path, $owner = null)
{
touch($path);
if ($owner) {
$this->chown($path, $owner);
}
}
/**
* Touch the given path as the non-root user.
*
* @param string $path
* @return void
*/
public function touchAsUser($path)
{
return $this->touch($path, user());
}
/**
* Determine if the given file exists.
*
* @param string $path
* @return bool
*/
public function exists($path)
{
return file_exists($path);
}
/**
* Read the contents of the given file.
*
* @param string $path
* @return string
*/
public function get($path)
{
return file_get_contents($path);
}
/**
* Write to the given file.
*
* @param string $path
* @param string $contents
* @param string|null $owner
* @return string
*/
public function put($path, $contents, $owner = null)
{
file_put_contents($path, $contents);
if ($owner) {
$this->chown($path, $owner);
}
}
/**
* Write to the given file as the non-root user.
*
* @param string $path
* @param string $contents
* @return string
*/
public function putAsUser($path, $contents)
{
return $this->put($path, $contents, user());
}
/**
* Delete the file at the given path.
*
* @param string $path
* @return void
*/
public function unlink($path)
{
@unlink($path);
}
/**
* Change the owner of the given path.
*
* @param string $path
* @param string $user
*/
public function chown($path, $user)
{
chown($path, $user);
}
/**
* Change the group of the given path.
*
* @param string $path
* @param string $group
*/
public function chgrp($path, $group)
{
chgrp($path, $group);
}
/**
* Resolve the given path.
*
* @param string $path
* @return string
*/
public function realpath($path)
{
return realpath($path);
}
/**
* Determine if the given path is a symbolic link.
*
* @param string $path
* @return bool
*/
public function isLink($path)
{
return is_link($path);
}
/**
* Resolve the given symbolic link.
*
* @param string $path
* @return string
*/
public function readLink($path)
{
return read_link($path);
}
}

152
tests/BrewTest.php Normal file
View File

@@ -0,0 +1,152 @@
<?php
use Valet\Brew;
use Valet\Filesystem;
use Valet\CommandLine;
use Illuminate\Container\Container;
class BrewTest extends PHPUnit_Framework_TestCase
{
public function setUp()
{
$_SERVER['SUDO_USER'] = 'Taylor';
Container::setInstance(new Container);
}
public function tearDown()
{
Mockery::close();
}
public function test_brew_can_be_resolved_from_container()
{
$this->assertInstanceOf(Brew::class, resolve(Brew::class));
}
public function test_installed_returns_true_when_given_formula_is_installed()
{
$cli = Mockery::mock(CommandLine::class);
$cli->shouldReceive('run')->with('brew list | grep php70')->andReturn('php70');
swap(CommandLine::class, $cli);
$this->assertTrue(resolve(Brew::class)->installed('php70'));
$cli = Mockery::mock(CommandLine::class);
$cli->shouldReceive('run')->with('brew list | grep php70')->andReturn('php70-mcrypt
php70');
swap(CommandLine::class, $cli);
$this->assertTrue(resolve(Brew::class)->installed('php70'));
}
public function test_installed_returns_false_when_given_formula_is_not_installed()
{
$cli = Mockery::mock(CommandLine::class);
$cli->shouldReceive('run')->with('brew list | grep php70')->andReturn('');
swap(CommandLine::class, $cli);
$this->assertFalse(resolve(Brew::class)->installed('php70'));
$cli = Mockery::mock(CommandLine::class);
$cli->shouldReceive('run')->with('brew list | grep php70')->andReturn('php70-mcrypt');
swap(CommandLine::class, $cli);
$this->assertFalse(resolve(Brew::class)->installed('php70'));
$cli = Mockery::mock(CommandLine::class);
$cli->shouldReceive('run')->with('brew list | grep php70')->andReturn('php70-mcrypt
php70-something-else
php7');
swap(CommandLine::class, $cli);
$this->assertFalse(resolve(Brew::class)->installed('php70'));
}
public function test_has_installed_php_indicates_if_php_is_installed_via_brew()
{
$brew = Mockery::mock(Brew::class.'[installed]', [new CommandLine, new Filesystem]);
$brew->shouldReceive('installed')->with('php70')->andReturn(true);
$brew->shouldReceive('installed')->with('php56')->andReturn(true);
$this->assertTrue($brew->hasInstalledPhp());
$brew = Mockery::mock(Brew::class.'[installed]', [new CommandLine, new Filesystem]);
$brew->shouldReceive('installed')->with('php70')->andReturn(true);
$brew->shouldReceive('installed')->with('php56')->andReturn(false);
$this->assertTrue($brew->hasInstalledPhp());
$brew = Mockery::mock(Brew::class.'[installed]', [new CommandLine, new Filesystem]);
$brew->shouldReceive('installed')->with('php70')->andReturn(false);
$brew->shouldReceive('installed')->with('php56')->andReturn(false);
$this->assertFalse($brew->hasInstalledPhp());
}
public function test_tap_taps_the_given_homebrew_repository()
{
$cli = Mockery::mock(CommandLine::class);
$cli->shouldReceive('passthru')->with('sudo -u Taylor brew tap php70');
$cli->shouldReceive('passthru')->with('sudo -u Taylor brew tap php56');
swap(CommandLine::class, $cli);
resolve(Brew::class)->tap('php70', 'php56');
}
public function test_restart_restarts_the_service_using_homebrew_services()
{
$cli = Mockery::mock(CommandLine::class);
$cli->shouldReceive('quietly')->with('sudo brew services restart dnsmasq');
swap(CommandLine::class, $cli);
resolve(Brew::class)->restartService('dnsmasq');
}
public function test_stop_stops_the_service_using_homebrew_services()
{
$cli = Mockery::mock(CommandLine::class);
$cli->shouldReceive('quietly')->with('sudo brew services stop dnsmasq');
swap(CommandLine::class, $cli);
resolve(Brew::class)->stopService('dnsmasq');
}
public function test_linked_php_returns_linked_php_formula_name()
{
$files = Mockery::mock(Filesystem::class);
$files->shouldReceive('isLink')->with('/usr/local/bin/php')->andReturn(true);
$files->shouldReceive('readLink')->with('/usr/local/bin/php')->andReturn('/test/path/php70/test');
swap(Filesystem::class, $files);
$this->assertEquals('php70', resolve(Brew::class)->linkedPhp());
$files = Mockery::mock(Filesystem::class);
$files->shouldReceive('isLink')->with('/usr/local/bin/php')->andReturn(true);
$files->shouldReceive('readLink')->with('/usr/local/bin/php')->andReturn('/test/path/php56/test');
swap(Filesystem::class, $files);
$this->assertEquals('php56', resolve(Brew::class)->linkedPhp());
}
/**
* @expectedException DomainException
*/
public function test_linked_php_throws_exception_if_no_php_link()
{
$files = Mockery::mock(Filesystem::class);
$files->shouldReceive('isLink')->with('/usr/local/bin/php')->andReturn(false);
swap(Filesystem::class, $files);
resolve(Brew::class)->linkedPhp();
}
/**
* @expectedException DomainException
*/
public function test_linked_php_throws_exception_if_unsupported_php_version_is_linked()
{
$files = Mockery::mock(Filesystem::class);
$files->shouldReceive('isLink')->with('/usr/local/bin/php')->andReturn(true);
$files->shouldReceive('readLink')->with('/usr/local/bin/php')->andReturn('/test/path/php42/test');
swap(Filesystem::class, $files);
resolve(Brew::class)->linkedPhp();
}
}

81
tests/CaddyTest.php Normal file
View File

@@ -0,0 +1,81 @@
<?php
use Valet\Caddy;
use Valet\Filesystem;
use Valet\CommandLine;
use Illuminate\Container\Container;
class CaddyTest extends PHPUnit_Framework_TestCase
{
public function setUp()
{
$_SERVER['SUDO_USER'] = 'Taylor';
Container::setInstance(new Container);
}
public function tearDown()
{
Mockery::close();
}
public function test_install_caddy_file_places_stub_in_valet_home_directory()
{
$files = Mockery::mock(Filesystem::class.'[putAsUser]');
$files->shouldReceive('putAsUser')->andReturnUsing(function ($path, $contents) {
$this->assertEquals(VALET_HOME_PATH.'/Caddyfile', $path);
$this->assertTrue(strpos($contents, 'import /Users/'.user().'/.valet/Caddy/*') !== false);
});
swap(Filesystem::class, $files);
$caddy = resolve(Caddy::class);
$caddy->installCaddyFile();
}
public function test_install_caddy_directories_creates_location_for_site_specific_configuration()
{
$files = Mockery::mock(Filesystem::class);
$files->shouldReceive('isDir')->with(VALET_HOME_PATH.'/Caddy')->andReturn(false);
$files->shouldReceive('mkdirAsUser')->with(VALET_HOME_PATH.'/Caddy');
$files->shouldReceive('touchAsUser')->with(VALET_HOME_PATH.'/Caddy/.keep');
swap(Filesystem::class, $files);
$caddy = resolve(Caddy::class);
$caddy->installCaddyDirectory();
}
public function test_caddy_directory_is_never_created_if_it_already_exists()
{
$files = Mockery::mock(Filesystem::class);
$files->shouldReceive('isDir')->with(VALET_HOME_PATH.'/Caddy')->andReturn(true);
$files->shouldReceive('mkdirAsUser')->never();
$files->shouldReceive('touchAsUser')->with(VALET_HOME_PATH.'/Caddy/.keep');
swap(Filesystem::class, $files);
$caddy = resolve(Caddy::class);
$caddy->installCaddyDirectory();
}
public function test_caddy_daemon_is_placed_in_correct_location()
{
$files = Mockery::mock(Filesystem::class.'[put]');
swap(Filesystem::class, $files);
$caddy = resolve(Caddy::class);
$files->shouldReceive('put')->andReturnUsing(function ($path, $contents) use ($caddy) {
$this->assertEquals($caddy->daemonPath, $path);
$this->assertTrue(strpos($contents, VALET_HOME_PATH) !== false);
});
$caddy->installCaddyDaemon();
}
}

122
tests/ConfigurationTest.php Normal file
View File

@@ -0,0 +1,122 @@
<?php
use Valet\Filesystem;
use Valet\Configuration;
use Illuminate\Container\Container;
class ConfigurationTest extends PHPUnit_Framework_TestCase
{
public function setUp()
{
$_SERVER['SUDO_USER'] = 'Taylor';
Container::setInstance(new Container);
}
public function tearDown()
{
Mockery::close();
}
public function test_configuration_directory_is_created_if_it_doesnt_exist()
{
$files = Mockery::mock(Filesystem::class);
$files->shouldReceive('isDir')->with(VALET_HOME_PATH)->andReturn(false);
$files->shouldReceive('mkdirAsUser')->with(VALET_HOME_PATH);
swap(Filesystem::class, $files);
resolve(Configuration::class)->createConfigurationDirectory();
$files = Mockery::mock(Filesystem::class);
$files->shouldReceive('isDir')->with(VALET_HOME_PATH)->andReturn(true);
$files->shouldReceive('mkdirAsUser')->never();
swap(Filesystem::class, $files);
resolve(Configuration::class)->createConfigurationDirectory();
}
public function test_drivers_directory_is_created_with_sample_driver_if_it_doesnt_exist()
{
$files = Mockery::mock(Filesystem::class.'[isDir,mkdirAsUser,putAsUser]');
$files->shouldReceive('isDir')->with(VALET_HOME_PATH.'/Drivers')->andReturn(false);
$files->shouldReceive('mkdirAsUser')->with(VALET_HOME_PATH.'/Drivers');
$files->shouldReceive('putAsUser');
swap(Filesystem::class, $files);
resolve(Configuration::class)->createDriversDirectory();
}
public function test_add_path_adds_a_path_to_the_paths_array_and_removes_duplicates()
{
$config = Mockery::mock(Configuration::class.'[read,write]', [new Filesystem]);
$config->shouldReceive('read')->andReturn([
'paths' => ['path-1', 'path-2'],
]);
$config->shouldReceive('write')->with([
'paths' => ['path-1', 'path-2', 'path-3'],
]);
$config->addPath('path-3');
$config = Mockery::mock(Configuration::class.'[read,write]', [new Filesystem]);
$config->shouldReceive('read')->andReturn([
'paths' => ['path-1', 'path-2', 'path-3'],
]);
$config->shouldReceive('write')->with([
'paths' => ['path-1', 'path-2', 'path-3'],
]);
$config->addPath('path-3');
}
public function test_paths_may_be_removed_from_the_configuration()
{
$config = Mockery::mock(Configuration::class.'[read,write]', [new Filesystem]);
$config->shouldReceive('read')->andReturn([
'paths' => ['path-1', 'path-2'],
]);
$config->shouldReceive('write')->with([
'paths' => ['path-1'],
]);
$config->removePath('path-2');
}
public function test_prune_removes_directories_from_paths_that_no_longer_exist()
{
$files = Mockery::mock(Filesystem::class.'[exists,isDir]');
swap(Filesystem::class, $files);
$files->shouldReceive('exists')->with(VALET_HOME_PATH.'/config.json')->andReturn(true);
$files->shouldReceive('isDir')->with('path-1')->andReturn(true);
$files->shouldReceive('isDir')->with('path-2')->andReturn(false);
$config = Mockery::mock(Configuration::class.'[read,write]', [$files]);
$config->shouldReceive('read')->andReturn([
'paths' => ['path-1', 'path-2'],
]);
$config->shouldReceive('write')->with([
'paths' => ['path-1'],
]);
$config->prune();
}
public function test_prune_doesnt_execute_if_configuration_directory_doesnt_exist()
{
$files = Mockery::mock(Filesystem::class.'[exists]');
swap(Filesystem::class, $files);
$files->shouldReceive('exists')->with(VALET_HOME_PATH.'/config.json')->andReturn(false);
$config = Mockery::mock(Configuration::class.'[read,write]', [$files]);
$config->shouldReceive('read')->never();
$config->shouldReceive('write')->never();
$config->prune();
}
public function test_update_key_updates_the_specified_configuration_key()
{
$config = Mockery::mock(Configuration::class.'[read,write]', [new Filesystem]);
$config->shouldReceive('read')->once()->andReturn(['foo' => 'bar']);
$config->shouldReceive('write')->once()->with(['foo' => 'bar', 'bar' => 'baz']);
$config->updateKey('bar', 'baz');
}
}

View File

@@ -11,10 +11,13 @@
}
use Silly\Application;
use Illuminate\Container\Container;
/**
* Create the application.
*/
Container::setInstance(new Container);
$app = new Application('Laravel Valet', 'v1.0.12');
/**
@@ -44,7 +47,7 @@
Valet\Caddy::restart();
$output->writeln(PHP_EOL.'<info>Valet installed successfully!</info>');
output(PHP_EOL.'<info>Valet installed successfully!</info>');
});
/**