Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,14 @@ You can run either all of your tests or a single testsuite with the following co

You can configure certain things by creating a `config.touchstone.php` file in the root of your project.

#### Directories For Tests

Here's how to set the directories for where your tests are located:

```php
<?php
# config.touchstone.php

return [
'directories' => [
'all' => 'tests',
Expand All @@ -116,6 +120,48 @@ return [
];
```

#### Plugins

Here's how to load plugins which are loaded before each test.

This means for a plugin like ACF (Advanced Custom Fields) you can use functions like `get_field()` in your code and it won't break your tests.

**Important:** You will need to provide the plugin files. I recommend putting them all in `bin/plugins/` in your theme/plugin and the adding that path to your `.gitignore`.

```php
<?php
# config.touchstone.php

return [
'plugins' => [
[
'name' => 'Advanced Custom Fields',
'file' => dirname(__FILE__) . '/bin/plugins/advanced-custom-fields-pro/acf.php',
],
],
];
```

```gitignore
# Directories
bin/plugins
```

#### Theme

Here's how to load a theme which is active for each test.

```php
<?php
# config.touchstone.php

return [
'theme' => [
'root' => dirname(__FILE__) . '/../../themes/twentytwentyone',
],
];
```

---

## Composer Scripts
Expand Down
10 changes: 8 additions & 2 deletions bin/touchstone
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
use Symfony\Component\Console\Application;
use WPTS\Console\Commands\Setup;
use WPTS\Console\Commands\Test;
use WPTS\Settings;

use const WPTS\NAME;
use const WPTS\VERSION;

$autoloader_files = [
'app' => __DIR__ . '/../vendor/autoload.php',
Expand All @@ -18,9 +22,11 @@ foreach ($autoloader_files as $env_key => $file) {
}
}

$app = new Application();
$app = new Application(NAME, VERSION);

$settings = new Settings();

$app->add(new Setup());
$app->add(new Test());
$app->add(new Test($settings));

$app->run();
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"league/flysystem": "^2.3",
"wp-cli/wp-config-transformer": "^1.2",
"symfony/process": "^5.3",
"yoast/phpunit-polyfills": "^1.0"
"yoast/phpunit-polyfills": "^1.0",
"php-stubs/wordpress-stubs": "^5.8"
},
"require-dev": {
"spatie/ray": "^1.26",
Expand Down
46 changes: 45 additions & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions inc/helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

namespace WPTS;

const VERSION = '1.0.0';
const NAME = 'Touchstone';
const VERSION = '1.2.0';

const CMD_INTRO = [
'<options=bold>Touchstone v' . VERSION,
'<options=bold>' . NAME . ' v' . VERSION,
'',
];

Expand Down
1 change: 0 additions & 1 deletion src/Console/Commands/Setup.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace WPTS\Console\Commands;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
Expand Down
80 changes: 18 additions & 62 deletions src/Console/Commands/Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,19 @@
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\Process;
use WPTS\TestsSettings;
use WPTS\UserConfiguration;
use WPTS\Settings;

class Test extends Command
{
protected static $defaultName = 'test';

protected string $appRoot;
protected string $consumerRoot;
protected string $consumerConfigurationFile;
protected string $phpunitExecutablePath;
protected string $phpunitConfigPath;
protected string $tmpDir;
protected Settings $appSettings;

public function __construct()
public function __construct(Settings $settings)
{
parent::__construct();

$this->appRoot = __DIR__ . '/../../../';
$this->consumerRoot = \exec('pwd') . '/';
$this->consumerConfigurationFile = $this->consumerRoot . 'config.touchstone.php';
$this->phpunitExecutablePath = $this->consumerRoot . 'vendor/bin/phpunit';
$this->phpunitConfigPath = $this->appRoot . 'phpunit-touchstone.xml';
$this->tmpDir = \sys_get_temp_dir();
}

protected function userConfiguration(): UserConfiguration
{
if (!\file_exists($this->consumerConfigurationFile)) {
return new UserConfiguration();
}

$config = include $this->consumerConfigurationFile;

if (!\is_array($config)) {
return new UserConfiguration();
}

return new UserConfiguration($config);
$this->appSettings = $settings;
}

protected function configure(): void
Expand All @@ -65,44 +39,38 @@ protected function execute(InputInterface $input, OutputInterface $output): int
{
$output->writeln(\WPTS\CMD_INTRO);

$settings = new TestsSettings();
try {
$output->writeln([
\WPTS\CMD_ICONS['loading'] . " Running {$input->getOption('type')} tests...",
'',
]);

$settings->testsDir = $this->consumerRoot . ($this->userConfiguration()->getTestsDirectory() ?: 'tests');
$settings->unitTestsDir = $this->consumerRoot . ($this->userConfiguration()->getUnitTestsDirectory() ?: 'tests/Unit');
$settings->integrationTestsDir = $this->consumerRoot . ($this->userConfiguration()->getIntegrationTestsDirectory() ?: 'tests/Integration');
$this->verifyTestFilesExist();

try {
$process_args = [
$this->phpunitExecutablePath,
$this->appSettings->phpunitExecutablePath(),
];

switch ($input->getOption('type')) {
case 'all':
$test_type_text = 'All';
$process_args[] = $settings->testsDir;
$process_args[] = $this->appSettings->testsDirectory();
break;
case 'unit':
$test_type_text = 'Unit';
$process_args[] = $settings->unitTestsDir;
$process_args[] = $this->appSettings->unitTestsDirectory();
break;
case 'integration':
$test_type_text = 'Integration';
$process_args[] = $settings->integrationTestsDir;
$process_args[] = $this->appSettings->integrationTestsDirectory();
break;
default:
$test_type_text = '';
break;
}

$process_args[] = '--config';
$process_args[] = $this->phpunitConfigPath;

$output->writeln([
\WPTS\CMD_ICONS['loading'] . " Running {$input->getOption('type')} tests...",
'',
]);

$this->preTestChecks();
$process_args[] = $this->appSettings->phpunitConfigPath();

$process = new Process($process_args);

Expand All @@ -122,23 +90,18 @@ protected function execute(InputInterface $input, OutputInterface $output): int
return Command::SUCCESS;
} catch (\Throwable $e) {
$output->writeln([
'',
\WPTS\CMD_ICONS['cross'] . " {$e->getMessage()}",
'',
]);

return Command::FAILURE;
}
}

protected function preTestChecks(): void
{
$this->verifyTestFilesExist();
}

protected function verifyTestFilesExist(): void
{
$wp_files_root = $this->tmpDir . '/wordpress';
$test_files_root = $this->tmpDir . '/wordpress-tests-lib';
$wp_files_root = $this->appSettings->tempDirectory() . '/wordpress';
$test_files_root = $this->appSettings->tempDirectory() . '/wordpress-tests-lib';

if (!\is_dir($wp_files_root)) {
throw new \InvalidArgumentException("Cannot find WordPress folder. Please run setup command.");
Expand All @@ -152,11 +115,4 @@ protected function verifyTestFilesExist(): void
throw new \InvalidArgumentException("Cannot find WordPress test files. Please run setup command.");
}
}

protected function verifyTestConfigExists(): void
{
if (!\file_exists($this->phpunitExecutablePath)) {
throw new \InvalidArgumentException("Cannot find PHPUnit config file. Please create a phpunit.xml file.");
}
}
}
71 changes: 71 additions & 0 deletions src/Consumer/ConsumerSettings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

namespace WPTS\Consumer;

class ConsumerSettings
{
protected string $testsDir = '';
protected string $unitTestsDir = '';
protected string $integrationTestsDir = '';

protected array $plugins = [];
protected Theme $theme;

public function __construct(string $root_path)
{
$file = $root_path . 'config.touchstone.php';

if (!\file_exists($file)) {
return;
}

$config = include $file;

if (!\is_array($config)) {
return;
}

$this->testsDir = $root_path . ($config['directories']['all'] ?? '');
$this->unitTestsDir = $root_path . ($config['directories']['unit'] ?? '');
$this->integrationTestsDir = $root_path . ($config['directories']['integration'] ?? '');

$this->plugins = \array_map(function (array $data) {
return new Plugin(
$data['name'] ?? '',
$data['file'] ?? '',
);
}, $config['plugins'] ?? []);

$theme_path = $config['theme']['root'] ?? '';

$this->theme = new Theme($theme_path);
}

public function testsDirectory(): string
{
return $this->testsDir;
}

public function unitTestsDirectory(): string
{
return $this->unitTestsDir;
}

public function integrationTestsDirectory(): string
{
return $this->integrationTestsDir;
}

/**
* @return Plugin[]
*/
public function plugins(): array
{
return $this->plugins;
}

public function theme(): Theme
{
return $this->theme;
}
}
Loading