diff --git a/src/Pest.php b/src/Pest.php index d9d56ff..59d70ae 100644 --- a/src/Pest.php +++ b/src/Pest.php @@ -14,6 +14,7 @@ use markhuot\craftpest\actions\RenderCompiledClasses; use markhuot\craftpest\behaviors\ExpectableBehavior; use markhuot\craftpest\behaviors\FieldTypeHintBehavior; +use markhuot\craftpest\behaviors\SnapshotableBehavior; use markhuot\craftpest\behaviors\TestableElementBehavior; use markhuot\craftpest\behaviors\TestableElementQueryBehavior; use markhuot\craftpest\console\PestController; @@ -39,6 +40,7 @@ function bootstrap($app) function (DefineBehaviorsEvent $event) { $event->behaviors[] = ExpectableBehavior::class; $event->behaviors[] = TestableElementBehavior::class; + $event->behaviors[] = SnapshotableBehavior::class; } ); diff --git a/src/behaviors/SnapshotableBehavior.php b/src/behaviors/SnapshotableBehavior.php new file mode 100644 index 0000000..d2da10f --- /dev/null +++ b/src/behaviors/SnapshotableBehavior.php @@ -0,0 +1,39 @@ +owner->toArray()) + ->except([ + 'id', 'postDate', 'sectionId', 'uid', 'siteSettingsId', + 'fieldLayoutId', 'contentId', 'dateCreated', 'dateUpdated', + 'canonicalId', 'typeId', + ]) + + // filter out any non-eager loaded queries because we can't snapshot on them, their + // values change too often between runs + ->filter(fn ($value, $handle) => ! ($this->owner->{$handle} instanceof ElementQuery)) + + // Remap any element collections (eager loaded relations) to their nested snapshots + ->map(function ($value, $handle) { + if ($this->owner->{$handle} instanceof ElementCollection) { + return $this->owner->{$handle}->map->toSnapshot(); + } + + return $value; + }) + ->all(); + } +} diff --git a/src/factories/Section.php b/src/factories/Section.php index bd0d0f9..f2b2d1f 100644 --- a/src/factories/Section.php +++ b/src/factories/Section.php @@ -13,7 +13,7 @@ * @method self name(string $name) * @method self handle(string $name) * @method self type(string $type) - * @method \craft\models\Section|Collection create() + * @method \craft\models\Section|Collection<\craft\models\Section> create(array $definition = []) */ class Section extends Factory { @@ -72,13 +72,23 @@ function newElement() */ function definition(int $index = 0) { $name = $this->faker->words(2, true); - $handle = StringHelper::toCamelCase($name); return [ 'name' => $name, - 'handle' => $handle, 'type' => 'channel', - 'siteSettings' => collect(\Craft::$app->sites->getAllSites())->mapWithkeys(function ($site) use ($name, $handle) { + ]; + } + + public function inferences(array $definition = []) + { + if (! empty($definition['name']) && empty($definition['handle'])) { + $definition['handle'] = StringHelper::toCamelCase($definition['name']); + } + + $name = $definition['name']; + $handle = $definition['handle']; + $definition['siteSettings'] = collect(\Craft::$app->sites->getAllSites()) + ->mapWithkeys(function ($site) use ($name, $handle) { $settings = new Section_SiteSettings(); $settings->siteId = $site->id; $settings->hasUrls = $this->hasUrls; @@ -90,8 +100,9 @@ function definition(int $index = 0) { ]); return [$site->id => $settings]; - })->toArray(), - ]; + })->toArray(); + + return $definition; } /** diff --git a/src/test/SnapshotAssertions.php b/src/test/SnapshotAssertions.php index a988446..eb98e73 100644 --- a/src/test/SnapshotAssertions.php +++ b/src/test/SnapshotAssertions.php @@ -2,6 +2,20 @@ namespace markhuot\craftpest\test; +/** + * # Snapshots + * + * A variety of snapshot assertions are available to help you test your HTML and DOM output in craft-pest. In + * many places you can simply expect an object `->toMatchSnapshot()` and Pest will handle the rest for you. + * + * For example, responses, DOM Lists, and views are all snapshotable. + * + * ```php + * it('matches responses')->get('/')->assertMatchesSnapshot(); + * it('matches dom lists')->get('/')->querySelector('h1')->assertMatchesSnapshot(); + * it('matches views')->renderTemplate('_news/entry', $variables)->assertMatchesSnapshot(); + * ``` + */ trait SnapshotAssertions { public function assertMatchesSnapshot() diff --git a/src/test/TestCase.php b/src/test/TestCase.php index bbf768d..a798133 100644 --- a/src/test/TestCase.php +++ b/src/test/TestCase.php @@ -7,6 +7,7 @@ use markhuot\craftpest\actions\CallSeeders; use markhuot\craftpest\actions\RenderCompiledClasses; use markhuot\craftpest\console\TestableResponse; +use markhuot\craftpest\web\ViewResponse; use Symfony\Component\Process\Process; class TestCase extends \PHPUnit\Framework\TestCase { @@ -235,4 +236,11 @@ public function console(array|string $command) return new TestableResponse($exitCode, $stdout, $stderr); } + public function renderTemplate(...$args) + { + $content = \Craft::$app->getView()->renderTemplate(...$args); + + return new \markhuot\craftpest\web\TestableResponse(['content' => $content]); + } + } diff --git a/tests/.pest/snapshots/SnapshotTest/it_asserts_dom_snapshots.snap b/tests/.pest/snapshots/SnapshotTest/it_asserts_dom_snapshots.snap new file mode 100644 index 0000000..d024baf --- /dev/null +++ b/tests/.pest/snapshots/SnapshotTest/it_asserts_dom_snapshots.snap @@ -0,0 +1,4 @@ +[ + "