Skip to content
This repository has been archived by the owner on Dec 12, 2023. It is now read-only.

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
* develop:
  keep loaded env variables in memory to avoid parsing .env multiple times
  add missing tests
  • Loading branch information
Baptouuuu committed Apr 15, 2020
2 parents ab813df + 169f68e commit c066674
Show file tree
Hide file tree
Showing 6 changed files with 509 additions and 6 deletions.
3 changes: 2 additions & 1 deletion composer.json
Expand Up @@ -33,6 +33,7 @@
},
"require-dev": {
"phpunit/phpunit": "~8.0",
"vimeo/psalm": "^3.7"
"vimeo/psalm": "^3.7",
"innmind/black-box": "^4.3"
}
}
10 changes: 6 additions & 4 deletions src/Application.php
Expand Up @@ -94,10 +94,12 @@ public function configAt(Path $path): self
$this->env,
$this->os,
$this->commands,
static fn(Environment $env, OperatingSystem $os): Environment => new DotEnvAware(
$env,
$os->filesystem(),
$path,
static fn(Environment $env, OperatingSystem $os): Environment => new KeepVariablesInMemory(
new DotEnvAware(
$env,
$os->filesystem(),
$path,
),
),
$this->enableSilentCartographer,
[],
Expand Down
76 changes: 76 additions & 0 deletions src/KeepVariablesInMemory.php
@@ -0,0 +1,76 @@
<?php
declare(strict_types = 1);

namespace Innmind\CLI\Framework;

use Innmind\CLI\{
Environment,
Environment\ExitCode,
};
use Innmind\Url\Path;
use Innmind\Stream\{
Readable,
Writable,
};
use Innmind\Immutable\{
Map,
Sequence,
};
use Symfony\Component\Dotenv\Dotenv;

final class KeepVariablesInMemory implements Environment
{
private Environment $env;
/** @var Map<string, string>|null */
private ?Map $variables = null;

public function __construct(Environment $env)
{
$this->env = $env;
}

public function interactive(): bool
{
return $this->env->interactive();
}

public function input(): Readable
{
return $this->env->input();
}

public function output(): Writable
{
return $this->env->output();
}

public function error(): Writable
{
return $this->env->error();
}

public function arguments(): Sequence
{
return $this->env->arguments();
}

public function variables(): Map
{
return $this->variables ??= $this->env->variables();
}

public function exit(int $code): void
{
$this->env->exit($code);
}

public function exitCode(): ExitCode
{
return $this->env->exitCode();
}

public function workingDirectory(): Path
{
return $this->env->workingDirectory();
}
}
10 changes: 9 additions & 1 deletion tests/ApplicationTest.php
Expand Up @@ -3,7 +3,10 @@

namespace Tests\Innmind\CLI\Framework;

use Innmind\CLI\Framework\Application;
use Innmind\CLI\Framework\{
Application,
KeepVariablesInMemory,
};
use Innmind\CLI\{
Environment,
Command,
Expand Down Expand Up @@ -274,6 +277,10 @@ public function testLoadDotEnv()
$command = new class implements Command {
public function __invoke(Environment $env, Arguments $arguments, Options $options): void
{
if (!$env instanceof KeepVariablesInMemory) {
throw new \Exception('Variables are not kept in memory');
}

if ($env->variables()->get('FOO') !== 'baz') {
throw new \Exception('Dot env do not override real variables');
}
Expand All @@ -297,6 +304,7 @@ public function toString(): string
$app2 = $app
->disableSilentCartographer()
->commands(function($env) use ($command) {
$this->assertInstanceOf(KeepVariablesInMemory::class, $env);
$this->assertSame('baz', $env->variables()->get('FOO'));

if (!$env->variables()->contains('BAR')) {
Expand Down
203 changes: 203 additions & 0 deletions tests/DotEnvAwareTest.php
@@ -0,0 +1,203 @@
<?php
declare(strict_types = 1);

namespace Tests\Innmind\CLI\Framework;

use Innmind\CLI\Framework\DotEnvAware;
use Innmind\CLI\{
Environment,
Environment\ExitCode,
};
use Innmind\OperatingSystem\Filesystem;
use Innmind\Stream\{
Readable,
Writable,
};
use PHPUnit\Framework\TestCase;
use Innmind\BlackBox\{
PHPUnit\BlackBox,
Set,
};
use Fixtures\Innmind\Url\Path;
use Fixtures\Innmind\Immutable\Sequence;

class DotEnvAwareTest extends TestCase
{
use BlackBox;

public function testInterface()
{
$this
->forAll(Path::any())
->then(function($path) {
$this->assertInstanceOf(
Environment::class,
new DotEnvAware(
$this->createMock(Environment::class),
$this->createMock(Filesystem::class),
$path,
),
);
});
}

public function testInteractive()
{
$this
->forAll(
Path::any(),
Set\Elements::of(true, false),
)
->then(function($path, $interactive) {
$env = new DotEnvAware(
$inner = $this->createMock(Environment::class),
$this->createMock(Filesystem::class),
$path,
);
$inner
->method('interactive')
->willReturn($interactive);

$this->assertSame($interactive, $env->interactive());
});
}

public function testInput()
{
$this
->forAll(Path::any())
->then(function($path) {
$env = new DotEnvAware(
$inner = $this->createMock(Environment::class),
$this->createMock(Filesystem::class),
$path,
);
$inner
->method('input')
->willReturn($input = $this->createMock(Readable::class));

$this->assertSame($input, $env->input());
});
}

public function testOutput()
{
$this
->forAll(Path::any())
->then(function($path) {
$env = new DotEnvAware(
$inner = $this->createMock(Environment::class),
$this->createMock(Filesystem::class),
$path,
);
$inner
->method('output')
->willReturn($output = $this->createMock(Writable::class));

$this->assertSame($output, $env->output());
});
}

public function testError()
{
$this
->forAll(Path::any())
->then(function($path) {
$env = new DotEnvAware(
$inner = $this->createMock(Environment::class),
$this->createMock(Filesystem::class),
$path,
);
$inner
->method('error')
->willReturn($error = $this->createMock(Writable::class));

$this->assertSame($error, $env->error());
});
}

public function testArguments()
{
$this
->forAll(
Path::any(),
Sequence::of('string', Set\Strings::any())
)
->then(function($path, $arguments) {
$env = new DotEnvAware(
$inner = $this->createMock(Environment::class),
$this->createMock(Filesystem::class),
$path,
);
$inner
->method('arguments')
->willReturn($arguments);

$this->assertSame($arguments, $env->arguments());
});
}

public function testExit()
{
$this
->forAll(
Path::any(),
Set\Integers::above(0),
)
->then(function($path, $code) {
$env = new DotEnvAware(
$inner = $this->createMock(Environment::class),
$this->createMock(Filesystem::class),
$path,
);
$inner
->expects($this->once())
->method('exit')
->with($code);

$this->assertNull($env->exit($code));
});
}

public function testExitCode()
{
$this
->forAll(
Path::any(),
Set\Integers::above(0),
)
->then(function($path, $code) {
$env = new DotEnvAware(
$inner = $this->createMock(Environment::class),
$this->createMock(Filesystem::class),
$path,
);
$inner
->method('exitCode')
->willReturn($expected = new ExitCode($code));

$this->assertSame($expected, $env->exitCode());
});
}

public function testWorkingDirectory()
{
$this
->forAll(
Path::any(),
Path::any(),
)
->then(function($path, $workingDirectory) {
$env = new DotEnvAware(
$inner = $this->createMock(Environment::class),
$this->createMock(Filesystem::class),
$path,
);
$inner
->method('workingDirectory')
->willReturn($workingDirectory);

$this->assertSame($workingDirectory, $env->workingDirectory());
});
}
}

0 comments on commit c066674

Please sign in to comment.