|
<?php |
|
declare(strict_types=1); |
|
|
|
namespace Zalas\Test\MarkdownSpec; |
|
|
|
use League\CommonMark\Block\Element\Document; |
|
use League\CommonMark\Block\Element\Heading; |
|
use League\CommonMark\DocParser; |
|
use League\CommonMark\Environment; |
|
use Webuni\CommonMark\TableExtension\Table; |
|
use Webuni\CommonMark\TableExtension\TableCell; |
|
use Webuni\CommonMark\TableExtension\TableExtension; |
|
use Webuni\CommonMark\TableExtension\TableRow; |
|
|
|
trait MarkdownSpec |
|
{ |
|
protected function executeScenarios(string $spec): void |
|
{ |
|
foreach ($this->loadEvents($spec) as $event) { |
|
$methodName = $this->eventCallback($event); |
|
|
|
if (!method_exists($this, $methodName)) { |
|
throw new \LogicException( |
|
sprintf('The %s::%s method does not exist.', get_called_class(), $methodName).PHP_EOL. |
|
PHP_EOL. |
|
sprintf('public function %s(Event $event) {}', $methodName) |
|
); |
|
} |
|
|
|
call_user_func([$this, $methodName], $event); |
|
} |
|
} |
|
|
|
protected function eventCallback(Event $event): string |
|
{ |
|
return sprintf('on%s', preg_replace('#[^a-z0-9_]#i', '', ucwords($event->name()))); |
|
} |
|
|
|
/** |
|
* @return Event[] |
|
*/ |
|
private function loadEvents(string $spec): array |
|
{ |
|
$document = $this->loadSpec($spec); |
|
$walker = $document->walker(); |
|
$events = []; |
|
$eventId = 0; |
|
|
|
while ($event = $walker->next()) { |
|
$node = $event->getNode(); |
|
|
|
if (!$event->isEntering()) { |
|
continue; |
|
} |
|
|
|
if ($node instanceof Heading) { |
|
$events[++$eventId] = Event::named($node->getStringContent()); |
|
} else if ($node instanceof Table) { |
|
$events[$eventId] = $events[$eventId]->withDataSet(new DataSet($this->readTableHeader($node), $this->readTableBody($node))); |
|
} |
|
} |
|
|
|
return $events; |
|
} |
|
|
|
private function loadSpec(string $spec): Document |
|
{ |
|
$environment = Environment::createCommonMarkEnvironment(); |
|
$environment->addExtension(new TableExtension()); |
|
|
|
return (new DocParser($environment))->parse(file_get_contents($spec)); |
|
} |
|
|
|
protected function readTableHeader(Table $node): array |
|
{ |
|
$header = []; |
|
$headWalker = $node->getHead()->walker(); |
|
|
|
while ($headEvent = $headWalker->next()) { |
|
$headNode = $headEvent->getNode(); |
|
if ($headNode instanceof TableCell && $headEvent->isEntering()) { |
|
$header[] = $headNode->getStringContent(); |
|
} |
|
} |
|
|
|
return $header; |
|
} |
|
|
|
protected function readTableBody(Table $node): array |
|
{ |
|
$tableWalker = $node->getBody()->walker(); |
|
$rows = []; |
|
$i = -1; |
|
while ($tableEvent = $tableWalker->next()) { |
|
$tableNode = $tableEvent->getNode(); |
|
if ($tableNode instanceof TableRow && $tableEvent->isEntering()) { |
|
$i = $i + 1; |
|
} |
|
if ($tableNode instanceof TableCell && $tableEvent->isEntering()) { |
|
$rows[$i][] = $tableNode->getStringContent(); |
|
} |
|
} |
|
|
|
return $rows; |
|
} |
|
} |