mirror of
https://github.com/Kovah/LinkAce.git
synced 2025-01-17 13:18:21 +01:00
Add audit log to lists and tags (#467)
This commit is contained in:
parent
ac13db9d5c
commit
18089253fe
@ -96,6 +96,7 @@ class ListController extends Controller
|
|||||||
|
|
||||||
return view('models.lists.show', [
|
return view('models.lists.show', [
|
||||||
'list' => $list,
|
'list' => $list,
|
||||||
|
'history' => $list->audits()->latest()->get(),
|
||||||
'listLinks' => $links,
|
'listLinks' => $links,
|
||||||
'route' => $request->getBaseUrl(),
|
'route' => $request->getBaseUrl(),
|
||||||
'orderBy' => $request->input('orderBy', 'created_at'),
|
'orderBy' => $request->input('orderBy', 'created_at'),
|
||||||
|
@ -97,6 +97,7 @@ class TagController extends Controller
|
|||||||
|
|
||||||
return view('models.tags.show', [
|
return view('models.tags.show', [
|
||||||
'tag' => $tag,
|
'tag' => $tag,
|
||||||
|
'history' => $tag->audits()->latest()->get(),
|
||||||
'tagLinks' => $links,
|
'tagLinks' => $links,
|
||||||
'route' => $request->getBaseUrl(),
|
'route' => $request->getBaseUrl(),
|
||||||
'orderBy' => $request->input('orderBy', 'created_at'),
|
'orderBy' => $request->input('orderBy', 'created_at'),
|
||||||
|
@ -89,7 +89,7 @@ class Link extends Model implements Auditable
|
|||||||
'icon',
|
'icon',
|
||||||
];
|
];
|
||||||
|
|
||||||
public $auditModifiers = [
|
public array $auditModifiers = [
|
||||||
'is_private' => BooleanModifier::class,
|
'is_private' => BooleanModifier::class,
|
||||||
'check_disabled' => BooleanModifier::class,
|
'check_disabled' => BooleanModifier::class,
|
||||||
'status' => LinkStatusModifier::class,
|
'status' => LinkStatusModifier::class,
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Audits\Modifiers\BooleanModifier;
|
||||||
use App\Scopes\OrderNameScope;
|
use App\Scopes\OrderNameScope;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
@ -12,6 +13,8 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
|||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use OwenIt\Auditing\Auditable as AuditableTrait;
|
||||||
|
use OwenIt\Auditing\Contracts\Auditable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class LinkList
|
* Class LinkList
|
||||||
@ -31,8 +34,9 @@ use Illuminate\Support\Str;
|
|||||||
* @method static Builder|Tag privateOnly()
|
* @method static Builder|Tag privateOnly()
|
||||||
* @method static Builder|Tag publicOnly()
|
* @method static Builder|Tag publicOnly()
|
||||||
*/
|
*/
|
||||||
class LinkList extends Model
|
class LinkList extends Model implements Auditable
|
||||||
{
|
{
|
||||||
|
use AuditableTrait;
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|
||||||
@ -50,6 +54,11 @@ class LinkList extends Model
|
|||||||
'is_private' => 'boolean',
|
'is_private' => 'boolean',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Audit settings
|
||||||
|
public array $auditModifiers = [
|
||||||
|
'is_private' => BooleanModifier::class,
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the OrderNameScope to the Tag model
|
* Add the OrderNameScope to the Tag model
|
||||||
*/
|
*/
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Audits\Modifiers\BooleanModifier;
|
||||||
use App\Scopes\OrderNameScope;
|
use App\Scopes\OrderNameScope;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
@ -11,6 +12,8 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
|
use OwenIt\Auditing\Auditable as AuditableTrait;
|
||||||
|
use OwenIt\Auditing\Contracts\Auditable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Tag
|
* Class Tag
|
||||||
@ -29,8 +32,9 @@ use Illuminate\Support\Carbon;
|
|||||||
* @method static Builder|Tag publicOnly()
|
* @method static Builder|Tag publicOnly()
|
||||||
* @method static Builder|Tag privateOnly()
|
* @method static Builder|Tag privateOnly()
|
||||||
*/
|
*/
|
||||||
class Tag extends Model
|
class Tag extends Model implements Auditable
|
||||||
{
|
{
|
||||||
|
use AuditableTrait;
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|
||||||
@ -45,6 +49,11 @@ class Tag extends Model
|
|||||||
'is_private' => 'boolean',
|
'is_private' => 'boolean',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Audit settings
|
||||||
|
public array $auditModifiers = [
|
||||||
|
'is_private' => BooleanModifier::class,
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the OrderNameScope to the Tag model
|
* Add the OrderNameScope to the Tag model
|
||||||
*/
|
*/
|
||||||
|
86
app/View/Components/History/ListEntry.php
Normal file
86
app/View/Components/History/ListEntry.php
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\View\Components\History;
|
||||||
|
|
||||||
|
use App\Models\Link;
|
||||||
|
use Illuminate\View\Component;
|
||||||
|
use OwenIt\Auditing\Models\Audit;
|
||||||
|
|
||||||
|
class ListEntry extends Component
|
||||||
|
{
|
||||||
|
public function __construct(private Audit $entry, private array $changes = [])
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
$timestamp = formatDateTime($this->entry->created_at);
|
||||||
|
|
||||||
|
if ($this->entry->event === 'deleted') {
|
||||||
|
$this->changes[] = trans('list.history_deleted');
|
||||||
|
} elseif ($this->entry->event === 'restored') {
|
||||||
|
$this->changes[] = trans('list.history_restored');
|
||||||
|
} else {
|
||||||
|
foreach ($this->entry->getModified() as $field => $change) {
|
||||||
|
$this->processChange($field, $change);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('components.history-entry', [
|
||||||
|
'timestamp' => $timestamp,
|
||||||
|
'changes' => $this->changes,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function processChange(string $field, array $changeData): void
|
||||||
|
{
|
||||||
|
$fieldName = trans('list.' . $field);
|
||||||
|
[$oldValue, $newValue] = $this->processValues($field, $changeData);
|
||||||
|
|
||||||
|
if ($oldValue === null) {
|
||||||
|
$change = trans('linkace.history_added', [
|
||||||
|
'fieldname' => $fieldName,
|
||||||
|
'newvalue' => htmlspecialchars($newValue),
|
||||||
|
]);
|
||||||
|
} elseif ($newValue === null) {
|
||||||
|
$change = trans('linkace.history_removed', [
|
||||||
|
'fieldname' => $fieldName,
|
||||||
|
'oldvalue' => htmlspecialchars($oldValue),
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
$change = trans('linkace.history_changed', [
|
||||||
|
'fieldname' => $fieldName,
|
||||||
|
'oldvalue' => htmlspecialchars($oldValue),
|
||||||
|
'newvalue' => htmlspecialchars($newValue),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->changes[] = $change;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply specialized methods for different fields to handle particular
|
||||||
|
* formatting needs of these fields.
|
||||||
|
*
|
||||||
|
* @param string $field
|
||||||
|
* @param array $changeData
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function processValues(string $field, array $changeData): array
|
||||||
|
{
|
||||||
|
$oldValue = $changeData['old'] ?? null;
|
||||||
|
$newValue = $changeData['new'] ?? null;
|
||||||
|
|
||||||
|
/** @var Link $model */
|
||||||
|
$model = app($this->entry->auditable_type);
|
||||||
|
|
||||||
|
if (isset($model->auditModifiers[$field])) {
|
||||||
|
$modifier = app($model->auditModifiers[$field]);
|
||||||
|
$oldValue = $modifier->modify($oldValue);
|
||||||
|
$newValue = $modifier->modify($newValue);
|
||||||
|
return [$oldValue, $newValue];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [$oldValue, $newValue];
|
||||||
|
}
|
||||||
|
}
|
86
app/View/Components/History/TagEntry.php
Normal file
86
app/View/Components/History/TagEntry.php
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\View\Components\History;
|
||||||
|
|
||||||
|
use App\Models\Link;
|
||||||
|
use Illuminate\View\Component;
|
||||||
|
use OwenIt\Auditing\Models\Audit;
|
||||||
|
|
||||||
|
class TagEntry extends Component
|
||||||
|
{
|
||||||
|
public function __construct(private Audit $entry, private array $changes = [])
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
$timestamp = formatDateTime($this->entry->created_at);
|
||||||
|
|
||||||
|
if ($this->entry->event === 'deleted') {
|
||||||
|
$this->changes[] = trans('tag.history_deleted');
|
||||||
|
} elseif ($this->entry->event === 'restored') {
|
||||||
|
$this->changes[] = trans('tag.history_restored');
|
||||||
|
} else {
|
||||||
|
foreach ($this->entry->getModified() as $field => $change) {
|
||||||
|
$this->processChange($field, $change);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('components.history-entry', [
|
||||||
|
'timestamp' => $timestamp,
|
||||||
|
'changes' => $this->changes,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function processChange(string $field, array $changeData): void
|
||||||
|
{
|
||||||
|
$fieldName = trans('tag.' . $field);
|
||||||
|
[$oldValue, $newValue] = $this->processValues($field, $changeData);
|
||||||
|
|
||||||
|
if ($oldValue === null) {
|
||||||
|
$change = trans('linkace.history_added', [
|
||||||
|
'fieldname' => $fieldName,
|
||||||
|
'newvalue' => htmlspecialchars($newValue),
|
||||||
|
]);
|
||||||
|
} elseif ($newValue === null) {
|
||||||
|
$change = trans('linkace.history_removed', [
|
||||||
|
'fieldname' => $fieldName,
|
||||||
|
'oldvalue' => htmlspecialchars($oldValue),
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
$change = trans('linkace.history_changed', [
|
||||||
|
'fieldname' => $fieldName,
|
||||||
|
'oldvalue' => htmlspecialchars($oldValue),
|
||||||
|
'newvalue' => htmlspecialchars($newValue),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->changes[] = $change;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply specialized methods for different fields to handle particular
|
||||||
|
* formatting needs of these fields.
|
||||||
|
*
|
||||||
|
* @param string $field
|
||||||
|
* @param array $changeData
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function processValues(string $field, array $changeData): array
|
||||||
|
{
|
||||||
|
$oldValue = $changeData['old'] ?? null;
|
||||||
|
$newValue = $changeData['new'] ?? null;
|
||||||
|
|
||||||
|
/** @var Link $model */
|
||||||
|
$model = app($this->entry->auditable_type);
|
||||||
|
|
||||||
|
if (isset($model->auditModifiers[$field])) {
|
||||||
|
$modifier = app($model->auditModifiers[$field]);
|
||||||
|
$oldValue = $modifier->modify($oldValue);
|
||||||
|
$newValue = $modifier->modify($newValue);
|
||||||
|
return [$oldValue, $newValue];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [$oldValue, $newValue];
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,11 @@ return [
|
|||||||
|
|
||||||
'name' => 'List Name',
|
'name' => 'List Name',
|
||||||
'description' => 'List Description',
|
'description' => 'List Description',
|
||||||
|
'is_private' => 'Private Status',
|
||||||
|
|
||||||
|
'history_deleted' => 'List was deleted',
|
||||||
|
'history_restored' => 'List was restored',
|
||||||
|
'history_created' => 'List was created',
|
||||||
|
|
||||||
'author' => 'by :user',
|
'author' => 'by :user',
|
||||||
|
|
||||||
|
@ -16,6 +16,11 @@ return [
|
|||||||
'private' => 'Private Tag',
|
'private' => 'Private Tag',
|
||||||
|
|
||||||
'name' => 'Tag Name',
|
'name' => 'Tag Name',
|
||||||
|
'is_private' => 'Private Status',
|
||||||
|
|
||||||
|
'history_deleted' => 'Tag was deleted',
|
||||||
|
'history_restored' => 'Tag was restored',
|
||||||
|
'history_created' => 'Tag was created',
|
||||||
|
|
||||||
'author' => 'by :user',
|
'author' => 'by :user',
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@
|
|||||||
<div class="link-history mt-5">
|
<div class="link-history mt-5">
|
||||||
<h3 class="h6 mb-2">@lang('link.history')</h3>
|
<h3 class="h6 mb-2">@lang('link.history')</h3>
|
||||||
|
|
||||||
<div class="small text-muted">
|
<div class="history small text-muted">
|
||||||
@foreach($history as $entry)
|
@foreach($history as $entry)
|
||||||
@if($loop->index === 5 && $loop->count >= 10)
|
@if($loop->index === 5 && $loop->count >= 10)
|
||||||
<a data-bs-toggle="collapse" href="#link-history" role="button" class="d-inline-block mb-1"
|
<a data-bs-toggle="collapse" href="#link-history" role="button" class="d-inline-block mb-1"
|
||||||
|
@ -48,12 +48,32 @@
|
|||||||
@lang('link.links')
|
@lang('link.links')
|
||||||
</div>
|
</div>
|
||||||
<div class="card-table">
|
<div class="card-table">
|
||||||
|
|
||||||
@include('models.links.partials.table', ['links' => $listLinks])
|
@include('models.links.partials.table', ['links' => $listLinks])
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{!! $listLinks->onEachSide(1)->withQueryString()->links() !!}
|
{!! $listLinks->onEachSide(1)->withQueryString()->links() !!}
|
||||||
|
|
||||||
|
<div class="list-history mt-5">
|
||||||
|
<h3 class="h6 mb-2">@lang('linkace.history')</h3>
|
||||||
|
|
||||||
|
<div class="history small text-muted">
|
||||||
|
@foreach($history as $entry)
|
||||||
|
@if($loop->index === 5 && $loop->count >= 10)
|
||||||
|
<a data-bs-toggle="collapse" href="#list-history" role="button" class="d-inline-block mb-1"
|
||||||
|
aria-expanded="false" aria-controls="list-history">
|
||||||
|
@lang('linkace.more')
|
||||||
|
<x-icon.caret-down class="fw"/>
|
||||||
|
</a>
|
||||||
|
<div id="list-history" class="collapse">
|
||||||
|
@endif
|
||||||
|
<x-history.list-entry :entry="$entry"/>
|
||||||
|
@endforeach
|
||||||
|
<div>{{ formatDateTime($list->created_at) }}: @lang('list.history_created')</div>
|
||||||
|
@if(count($history) >= 10)
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
@endsection
|
@endsection
|
||||||
|
@ -47,4 +47,26 @@
|
|||||||
|
|
||||||
{!! $tagLinks->onEachSide(1)->withQueryString()->links() !!}
|
{!! $tagLinks->onEachSide(1)->withQueryString()->links() !!}
|
||||||
|
|
||||||
|
<div class="list-history mt-5">
|
||||||
|
<h3 class="h6 mb-2">@lang('linkace.history')</h3>
|
||||||
|
|
||||||
|
<div class="history small text-muted">
|
||||||
|
@foreach($history as $entry)
|
||||||
|
@if($loop->index === 5 && $loop->count >= 10)
|
||||||
|
<a data-bs-toggle="collapse" href="#tag-history" role="button" class="d-inline-block mb-1"
|
||||||
|
aria-expanded="false" aria-controls="tag-history">
|
||||||
|
@lang('linkace.more')
|
||||||
|
<x-icon.caret-down class="fw"/>
|
||||||
|
</a>
|
||||||
|
<div id="tag-history" class="collapse">
|
||||||
|
@endif
|
||||||
|
<x-history.tag-entry :entry="$entry"/>
|
||||||
|
@endforeach
|
||||||
|
<div>{{ formatDateTime($tag->created_at) }}: @lang('tag.history_created')</div>
|
||||||
|
@if(count($history) >= 10)
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
@endsection
|
@endsection
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Components;
|
namespace Tests\Components\History;
|
||||||
|
|
||||||
use App\Models\Link;
|
use App\Models\Link;
|
||||||
use App\Models\LinkList;
|
use App\Models\LinkList;
|
||||||
@ -10,18 +10,16 @@ use App\View\Components\History\LinkEntry;
|
|||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class HistoryEntryTest extends TestCase
|
class LinkEntryTest extends TestCase
|
||||||
{
|
{
|
||||||
use RefreshDatabase;
|
use RefreshDatabase;
|
||||||
|
|
||||||
private User $user;
|
|
||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$this->user = User::factory()->create();
|
$user = User::factory()->create();
|
||||||
$this->actingAs($this->user);
|
$this->actingAs($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAddedChange(): void
|
public function testAddedChange(): void
|
86
tests/Components/History/ListEntryTest.php
Normal file
86
tests/Components/History/ListEntryTest.php
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Components\History;
|
||||||
|
|
||||||
|
use App\Models\LinkList;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\View\Components\History\ListEntry;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class ListEntryTest extends TestCase
|
||||||
|
{
|
||||||
|
use RefreshDatabase;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$user = User::factory()->create();
|
||||||
|
$this->actingAs($user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddedChange(): void
|
||||||
|
{
|
||||||
|
$list = LinkList::factory()->create([
|
||||||
|
'description' => null,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$list->update(['description' => 'Test Description']);
|
||||||
|
|
||||||
|
$historyEntry = $list->audits()->first();
|
||||||
|
|
||||||
|
$output = (new ListEntry($historyEntry))->render();
|
||||||
|
|
||||||
|
$this->assertStringContainsString('Added <code>Test Description</code> to List Description', $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRegularChange(): void
|
||||||
|
{
|
||||||
|
$list = LinkList::factory()->create([
|
||||||
|
'description' => 'Test Description',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$list->update(['description' => 'New Description']);
|
||||||
|
|
||||||
|
$historyEntry = $list->audits()->first();
|
||||||
|
|
||||||
|
$output = (new ListEntry($historyEntry))->render();
|
||||||
|
|
||||||
|
$this->assertStringContainsString(
|
||||||
|
'Changed List Description from <code>Test Description</code> to <code>New Description</code>',
|
||||||
|
$output
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRemoveChange(): void
|
||||||
|
{
|
||||||
|
$list = LinkList::factory()->create([
|
||||||
|
'description' => 'Test Description',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$list->update(['description' => null]);
|
||||||
|
|
||||||
|
$historyEntry = $list->audits()->first();
|
||||||
|
|
||||||
|
$output = (new ListEntry($historyEntry))->render();
|
||||||
|
|
||||||
|
$this->assertStringContainsString('Removed <code>Test Description</code> from List Description', $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testModelDeletion(): void
|
||||||
|
{
|
||||||
|
$list = LinkList::factory()->create();
|
||||||
|
|
||||||
|
$list->delete();
|
||||||
|
$list->restore();
|
||||||
|
|
||||||
|
$historyEntries = $list->audits()->get();
|
||||||
|
|
||||||
|
$output = (new ListEntry($historyEntries[0]))->render();
|
||||||
|
$this->assertStringContainsString('List was deleted', $output);
|
||||||
|
|
||||||
|
$output = (new ListEntry($historyEntries[1]))->render();
|
||||||
|
$this->assertStringContainsString('List was restored', $output);
|
||||||
|
}
|
||||||
|
}
|
58
tests/Components/History/TagEntryTest.php
Normal file
58
tests/Components/History/TagEntryTest.php
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Components\History;
|
||||||
|
|
||||||
|
use App\Models\LinkList;
|
||||||
|
use App\Models\Tag;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\View\Components\History\ListEntry;
|
||||||
|
use App\View\Components\History\TagEntry;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class TagEntryTest extends TestCase
|
||||||
|
{
|
||||||
|
use RefreshDatabase;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$user = User::factory()->create();
|
||||||
|
$this->actingAs($user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRegularChange(): void
|
||||||
|
{
|
||||||
|
$tag = Tag::factory()->create([
|
||||||
|
'name' => 'Test Tag',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$tag->update(['name' => 'New Tag']);
|
||||||
|
|
||||||
|
$historyEntry = $tag->audits()->first();
|
||||||
|
|
||||||
|
$output = (new TagEntry($historyEntry))->render();
|
||||||
|
|
||||||
|
$this->assertStringContainsString(
|
||||||
|
'Changed Tag Name from <code>Test Tag</code> to <code>New Tag</code>',
|
||||||
|
$output
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testModelDeletion(): void
|
||||||
|
{
|
||||||
|
$tag = Tag::factory()->create();
|
||||||
|
|
||||||
|
$tag->delete();
|
||||||
|
$tag->restore();
|
||||||
|
|
||||||
|
$historyEntries = $tag->audits()->get();
|
||||||
|
|
||||||
|
$output = (new TagEntry($historyEntries[0]))->render();
|
||||||
|
$this->assertStringContainsString('Tag was deleted', $output);
|
||||||
|
|
||||||
|
$output = (new TagEntry($historyEntries[1]))->render();
|
||||||
|
$this->assertStringContainsString('Tag was restored', $output);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user