Skip to content

Commit

Permalink
Adds support for supplying customizable fields in a given workflow/run
Browse files Browse the repository at this point in the history
  • Loading branch information
craigpaul committed Sep 11, 2024
1 parent eebbdc3 commit 0972f43
Show file tree
Hide file tree
Showing 8 changed files with 247 additions and 21 deletions.
20 changes: 18 additions & 2 deletions src/Console/Commands/TestMakeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,23 @@

use Illuminate\Console\GeneratorCommand;
use Illuminate\Support\Str;
use Symfony\Component\Console\Attribute\AsCommand;

#[AsCommand('make:blitz', 'Create a new test class')]
class TestMakeCommand extends GeneratorCommand
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'make:blitz {name} {--F|fields : Adjust the scaffolded test to allow for custom fields to be provided}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Create a new test class';

/**
* The type of class being generated.
*
Expand All @@ -23,6 +35,10 @@ class TestMakeCommand extends GeneratorCommand
*/
protected function getStub()
{
if ($this->option('fields')) {
return __DIR__.'/stubs/test.fields.stub';
}

return __DIR__.'/stubs/test.stub';
}

Expand Down
30 changes: 30 additions & 0 deletions src/Console/Commands/stubs/test.fields.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace {{ namespace }};

use CraigPaul\Blitz\Testing\TestCase;

class {{ class }} extends TestCase
{
/**
* Set up the workflow to be put under load.
*
* @return void
*/
public function handle(): void
{
//
}

/**
* Set up the dynamic fields for this workflow.
*
* @return array
*/
public function fields(): array
{
return [
//
]
}
}
13 changes: 12 additions & 1 deletion src/Http/Controllers/WorkflowController.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,18 @@ public function index(): JsonResponse
),
);

$workflows = array_map(fn (SplFileInfo $file) => Workflow::fromFile($file)->className(), $files);
$workflows = array_map(function (SplFileInfo $file) {
$workflow = Workflow::fromFile($file);
$namespace = $workflow->className;
$fields = $workflow->customizable
? $this->app->make($namespace)->fields()
: [];

return [
'fields' => $fields,
'namespace' => $namespace,
];
}, $files);

return $this->response->json($workflows);
}
Expand Down
66 changes: 66 additions & 0 deletions src/Support/Field.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

namespace CraigPaul\Blitz\Support;

use JsonSerializable;

class Field implements JsonSerializable
{
/**
* Create a new Field instance.
*
* @param string|null $description
* @param string $label
* @param string $name
* @param \CraigPaul\Blitz\Support\Option[] $options
* @param string|null $placeholder
* @param \CraigPaul\Blitz\Support\FieldType $type
*/
public function __construct(
public readonly ?string $description,
public readonly string $label,
public readonly string $name,
public readonly array $options = [],
public readonly ?string $placeholder,
public readonly FieldType $type,
) {
}

/**
* @inheritDoc
*/
public function jsonSerialize(): mixed
{
return [
'description' => $this->description,
'label' => $this->label,
'name' => $this->name,
'options' => $this->options,
'placeholder' => $this->placeholder,
'type' => $this->type,
];
}

/**
* Create a new Field instance with a type of select.
*
* @param string|null $description
* @param string $label
* @param string $name
* @param \CraigPaul\Blitz\Support\Option[] $options
* @param string|null $placeholder
*
* @return static
*/
public static function select(?string $description = null, string $label, string $name, array $options, ?string $placeholder): static
{
return new static(
description: $description,
label: $label,
name: $name,
options: $options,
placeholder: $placeholder,
type: FieldType::Select,
);
}
}
8 changes: 8 additions & 0 deletions src/Support/FieldType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace CraigPaul\Blitz\Support;

enum FieldType: string
{
case Select = 'select';
}
33 changes: 33 additions & 0 deletions src/Support/Option.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace CraigPaul\Blitz\Support;

use JsonSerializable;

class Option implements JsonSerializable
{
/**
* Create a new Option instance.
*
* @param string $text
* @param bool|int|float|string|null $value
*
* @return void
*/
public function __construct(
public readonly string $text,
public readonly bool|int|float|string|null $value,
) {
}

/**
* @inheritDoc
*/
public function jsonSerialize(): mixed
{
return [
'text' => $this->text,
'value' => $this->value,
];
}
}
68 changes: 51 additions & 17 deletions src/Support/Workflow.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,16 @@ class Workflow
/**
* Create a new Workflow instance.
*
* @param string $className
* @param bool $customizable
* @param string $name
* @param string $path
*
* @return void
*/
public function __construct(
public readonly string $className,
public readonly bool $customizable,
public readonly string $name,
public readonly string $path,
) {
Expand All @@ -38,34 +42,64 @@ public function __construct(
*/
public static function fromFile(SplFileInfo $file): static
{
return new static(
$path = $file->getPathname();

$instance = new static(
// TODO: The way this className property is generated precludes it from being more then a single directory deep. It will only work with files inside of `tests/Blitz`.
className: str_replace(
['/', '.php'],
['\\', ''],
ucfirst(
ltrim(
array_reverse(
explode(rtrim(base_path('/'), '/'), $path, 2)
)[0],
'/',
),
),
),
customizable: self::fileContains($file, 'public function fields()'),
name: ucfirst(
strtolower(
implode(' ', preg_split('/(?=\p{Lu})/u', strstr($file->getFilename(), 'Test.php', true), -1, PREG_SPLIT_NO_EMPTY)),
),
),
path: $file->getPathname(),
path: $path,
);

return $instance;
}

/**
* Convert the current path into the appropriate PSR-4 compatible namespace.
* Determine if the given file contains the given needle.
*
* @return string
* @param \SplFileInfo $file
* @param string $needle
*
* @return bool
*/
public function className(): string
protected static function fileContains(SplFileInfo $file, string $needle): bool
{
return str_replace(
['/', '.php'],
['\\', ''],
ucfirst(
ltrim(
array_reverse(
explode(rtrim(base_path('/'), '/'), $this->path, 2)
)[0],
'/',
),
),
);
if ($file->isReadable() === false) {
return false;
}

$handle = fopen($file->getRealPath(), 'r');

if ($handle === false) {
return false;
}

while (($line = fgets($handle)) !== false) {
if (strpos($line, $needle) !== false) {
fclose($handle);

return true;
}
}

fclose($handle);

return false;
}
}
30 changes: 29 additions & 1 deletion tests/CanRetrieveWorkflowNamespacesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace CraigPaul\Blitz\Tests;

use Illuminate\Testing\Fluent\AssertableJson;
use Mockery\MockInterface;

class CanRetrieveWorkflowNamespacesTest extends TestCase
{
Expand All @@ -12,6 +13,33 @@ public function testCanRetrieveExistingWorkflowNamespaces()
->getJson(route('blitz.workflows'))
->assertOk()
->assertJsonCount(1)
->assertJson(fn (AssertableJson $json) => $json->where('0', 'Tests\\Blitz\\ExampleTest'));
->assertJson(fn (AssertableJson $json) => $json->where('0', [
'fields' => [],
'namespace' => 'Tests\\Blitz\\ExampleTest',
]));
}

public function testCanSupplyOptionsWithWorkflows()
{
$this->artisan('make:blitz ExampleOptionableLoadTest --fields')->assertOk();

$this->mock('Tests\\Blitz\\ExampleOptionableLoadTest', function (MockInterface $mock) {
return $mock->shouldReceive('options')
->andReturn([
'foo' => 'bar',
])
->getMock();
});

$this->withoutExceptionHandling()
->getJson(route('blitz.workflows'))
->assertOk()
->assertJsonCount(2)
->assertJson(fn (AssertableJson $json) => $json->where('0', [
'fields' => [
'foo' => 'bar',
],
'namespace' => 'Tests\\Blitz\\ExampleOptionableLoadTest',
]));
}
}

0 comments on commit 0972f43

Please sign in to comment.