Skip to content

Commit

Permalink
better coverage for components controller
Browse files Browse the repository at this point in the history
  • Loading branch information
markhuot committed Dec 22, 2023
1 parent 238779c commit f9043ef
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 38 deletions.
1 change: 1 addition & 0 deletions .run/Pest.run.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Pest" type="PestRunConfigurationType">
<CommandLine parameters="-d memory_limit=-1" />
<option name="pestRunnerSettings">
<PestRunner directory="$PROJECT_DIR$/tests" method="" />
</option>
Expand Down
73 changes: 40 additions & 33 deletions src/actions/MakeModelFromArray.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use craft\base\FieldInterface;
use craft\base\Model;
use markhuot\keystone\db\ActiveRecord;
use markhuot\keystone\exceptions\RecordNotFound;
use yii\base\ModelEvent;

use function markhuot\keystone\helpers\base\app;
Expand Down Expand Up @@ -33,49 +34,55 @@ class MakeModelFromArray
* @param class-string<T> $className
* @return T
*/
public function handle(string $className, mixed $data, $validate = true, $errorOnMissing = false, $createOnMissing = true): mixed
public function handle(string $className, mixed $data, $validate = true, $errorOnMissing = true, $createOnMissing = true): mixed
{
if (is_subclass_of($className, ActiveRecord::class)) {
$primaryKey = $className::primaryKey();
if (! is_array($primaryKey)) {
$primaryKey = [$primaryKey];
}
$condition = array_flip($primaryKey);
foreach ($condition as $key => &$value) {
if (is_array($data)) {
$value = $data[$key];
}
// if (count($condition) === 1) {
// $value = $data;
// }
}
$condition = array_filter($condition);
$model = match (true) {
is_subclass_of($className, ActiveRecord::class) => $this->getRecordByPrimaryKey($className, $data),
$className === ElementInterface::class => app()->getElements()->getElementById($data),
$className === FieldInterface::class => app()->getFields()->getFieldById($data),
default => new $className,
};

if (count($condition)) {
$model = $className::findOne($condition);
}
} elseif ($className === ElementInterface::class) {
$model = app()->getElements()->getElementById($data);
} elseif ($className === FieldInterface::class) {
$model = app()->getFields()->getFieldById($data);
if ($errorOnMissing && empty($model)) {
throw new RecordNotFound('Record not found');
}

if (empty($model) && $createOnMissing) {
$model = new $className;
}
if ($model) {
$this->load($model, $data);

if (empty($model) && $errorOnMissing) {
throw new \RuntimeException('Could not find a matching '.$className);
if ($validate) {
$this->validate($model);
}
}

if (empty($model)) {
return null;
return $model;
}

protected function getRecordByPrimaryKey(string $className, mixed $data): ?ActiveRecord
{
$primaryKeyFields = $className::primaryKey();

// If primaryKey is a single field and a single value was passed in to $data assume
// the primaryKey field name
if (count($primaryKeyFields) === 1 && (is_string($data) || is_numeric($data))) {
$data = [$primaryKeyFields[0] => $data];
}

$this->load($model, $data);
// check to make sure that either all the primary key fields are present in the
// data array or _none_ of the primary key fields are present
$searchedKeyFields = collect($data)->keys()->intersect($primaryKeyFields);
if (count($searchedKeyFields) !== 0 && count($searchedKeyFields) !== count($primaryKeyFields)) {
throw new \RuntimeException('Missing primary key fields');
}

if ($validate) {
$this->validate($model);
// If all the primary key fields are present in the data array then use them to
// search for a model
if (count($searchedKeyFields) > 0) {
$condition = collect($data)->only($searchedKeyFields)->toArray();
$model = $className::findOne($condition);
}
else {
$model = new $className;
}

return $model;
Expand Down
8 changes: 8 additions & 0 deletions src/exceptions/RecordNotFound.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace markhuot\keystone\exceptions;

class RecordNotFound extends \Exception
{
//
}
5 changes: 0 additions & 5 deletions tests/ExportsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,6 @@
expect($component->getSummary())->toBe('bar');
});

it('skips exports unless instructed', function () {
$component = Component::factory()->type('site/components/skipped-export')->create();
$component->render();
});

it('skips exports when not accessed', function () {
$component = Component::factory()->type('site/components/skipped-export')->create();
$bar = $component->getType()->getExports()['exports']->get('bar');
Expand Down
23 changes: 23 additions & 0 deletions tests/RouteTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use craft\helpers\UrlHelper;
use markhuot\craftpest\factories\Entry;
use markhuot\craftpest\factories\User;
use markhuot\keystone\models\Component;

it('loads add panel', function () {
Expand Down Expand Up @@ -101,3 +102,25 @@
->assertOk()
->assertJsonPath('message', 'Component moved');
});

it('toggles a component\'s disclosure', function () {
/** @var Component $component */
$component = Component::factory()
->type('keystone/section')
->elementId(Entry::factory()->section('pages')->create()->id)
->create();
$url = UrlHelper::actionUrl('keystone/components/toggle-disclosure', [
'id' => $component->id,
'elementId' => $component->elementId,
'fieldId' => $component->fieldId,
]);
$user = User::factory()->admin(true)->create();

$this->actingAs($user)->postJson($url)->assertOk();
$component->refresh();
expect($component->isCollapsed())->toBe(true);

$this->actingAs($user)->postJson($url)->assertOk();
$component->refresh();
expect($component->isCollapsed())->toBe(false);
});

0 comments on commit f9043ef

Please sign in to comment.