From: Dan Brown Date: Mon, 3 Apr 2023 14:46:01 +0000 (+0100) Subject: Developed base testing and environment further X-Git-Url: http://source.bookstackapp.com/system-cli/commitdiff_plain/e78fd5f8be1d197fb794ebf6003cc1f64f0c09a3 Developed base testing and environment further --- diff --git a/Dockerfile b/Dockerfile index cd441d3..b257de4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,20 @@ RUN set -xe && \ php8.1-xml php8.1-zip php8.1-gd php8.1-bcmath php8.1-mysql php8.1-xdebug # Install composer to a custom location -RUN mkdir /scripts && \ - curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer + +# Clone down a BookStack instance for us to play with +RUN mkdir -p /var/www/bookstack && \ + cd /var/www/bookstack && \ + git clone https://github.com/BookStackApp/BookStack.git --branch release --single-branch ./ && \ + composer install --no-dev && \ + cp .env.example .env && \ + php artisan key:generate + +# Update env options +RUN sed -i 's/^DB_HOST=.*/DB_HOST=db/' /var/www/bookstack/.env && \ + sed -i 's/^DB_DATABASE=.*/DB_DATABASE=bookstack/' /var/www/bookstack/.env && \ + sed -i 's/^DB_USERNAME=.*/DB_USERNAME=bookstack/' /var/www/bookstack/.env && \ + sed -i 's/^DB_PASSWORD=.*/DB_PASSWORD=bookstack/' /var/www/bookstack/.env CMD ["/bin/bash"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index a2054b5..9499d98 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,6 +3,7 @@ version: "3.8" services: app: build: . + working_dir: /cli volumes: - ./:/cli depends_on: diff --git a/readme.md b/readme.md index 186222f..22bd0c3 100644 --- a/readme.md +++ b/readme.md @@ -25,14 +25,19 @@ This can be done by running the compile file: php compile.php ``` +Tests can be ran via PHPUnit within the docker environment as described below. **It is not advised** to run tests outside of this docker environment since tests are written to an expected pre-configured system environment. + #### Docker Environment A docker-compose setup exists to create a clean, contained environment, which is important for this project since the CLI checks and interacts with many system-level elements. ```bash +# Build the environment container +docker compose build + # Enter the environment -docker compose run -w /cli app +docker compose run app # From there you'll be dropped into a bash shell within the project directory. # You could proceed to install dependencies via composer via: @@ -40,8 +45,13 @@ composer install # Then you can run tests via: vendor/bin/phpunit + +# To clean-up and delete the environment: +docker compose rm -fsv ``` +Within the environment a pre-existing BookStack instance can be found at `/var/www/bookstack` for testing. + ### Contributing I welcome issues and PRs but keep in mind that I'd like to keep the feature-set narrow to limit support/maintenance burden. diff --git a/src/app.php b/src/app.php index 2a6a8b8..0ff90cd 100644 --- a/src/app.php +++ b/src/app.php @@ -15,4 +15,5 @@ $app->add(new UpdateCommand()); $app->add(new InitCommand()); $app->add(new RestoreCommand()); + return $app; \ No newline at end of file diff --git a/tests/CommandResult.php b/tests/CommandResult.php new file mode 100644 index 0000000..b8ee3b0 --- /dev/null +++ b/tests/CommandResult.php @@ -0,0 +1,37 @@ +tester->getStatusCode()); + } + + public function assertErrorExit(): void + { + Assert::assertTrue($this->error !== null); + } + + public function assertStdoutContains(string $needle): void + { + Assert::assertStringContainsString($needle, $this->tester->getDisplay()); + } + + public function assertStderrContains(string $needle): void + { + Assert::assertStringContainsString($needle, $this->error->getMessage() ?? ''); + } + + +} \ No newline at end of file diff --git a/tests/Commands/InitCommandTest.php b/tests/Commands/InitCommandTest.php index 294521b..42908a8 100644 --- a/tests/Commands/InitCommandTest.php +++ b/tests/Commands/InitCommandTest.php @@ -11,8 +11,8 @@ class InitCommandTest extends TestCase $dir = $this->getEmptyTestDir(); chdir($dir); - $commandTester = $this->runCommand('init'); - $commandTester->assertCommandIsSuccessful(); + $result = $this->runCommand('init'); + $result->assertSuccessfulExit(); $this->assertFileExists($dir . '/vendor/autoload.php'); $this->assertFileExists($dir . '/.env'); @@ -20,8 +20,28 @@ class InitCommandTest extends TestCase $envData = file_get_contents($dir . '/.env'); $this->assertMatchesRegularExpression('/^APP_KEY=base64:.{30,60}$/m', $envData); - $output = $commandTester->getDisplay(); - $this->assertStringContainsString("A BookStack install has been initialized at: " . $dir, $output); + $result->assertStdoutContains("A BookStack install has been initialized at: " . $dir); + + $this->deleteDirectory($dir); + } + + public function test_command_custom_path_validation() + { + $dir = $this->getEmptyTestDir(); + $file = $dir . '/out.txt'; + file_put_contents($file, 'hello'); + + $result = $this->runCommand('init', ['target-directory' => $file]); + $result->assertErrorExit(); + $result->assertStderrContains("Was provided [{$file}] as an install path but existing file provided."); + + $result = $this->runCommand('init', ['target-directory' => $dir]); + $result->assertErrorExit(); + $result->assertStderrContains("Expected install directory to be empty but existing files found in [{$dir}] target location."); + + $result = $this->runCommand('init', ['target-directory' => '/my/duck/says/hello']); + $result->assertErrorExit(); + $result->assertStderrContains("Could not resolve provided [/my/duck/says/hello] path to an existing folder."); $this->deleteDirectory($dir); } diff --git a/tests/TestCase.php b/tests/TestCase.php index 4cd1bcd..92cc2b6 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -40,14 +40,20 @@ class TestCase extends \PHPUnit\Framework\TestCase return require dirname(__DIR__) . '/src/app.php'; } - protected function runCommand(string $command, array $args = []): CommandTester + protected function runCommand(string $command, array $args = []): CommandResult { $app = $this->getApp(); $command = $app->find($command); + $err = null; $commandTester = new CommandTester($command); - $commandTester->execute($args); - return $commandTester; + try { + $commandTester->execute($args); + } catch (\Exception $exception) { + $err = $exception; + } + + return new CommandResult($commandTester, $err); } } \ No newline at end of file