MTM Laravel v12 #31

Merged
jonny merged 4 commits from develop into main 2025-04-04 18:10:47 +02:00
101 changed files with 2075 additions and 2879 deletions

View file

@ -12,7 +12,9 @@ APP_FALLBACK_LOCALE=en
APP_FAKER_LOCALE=en_US APP_FAKER_LOCALE=en_US
APP_MAINTENANCE_DRIVER=file APP_MAINTENANCE_DRIVER=file
APP_MAINTENANCE_STORE=database # APP_MAINTENANCE_STORE=database
PHP_CLI_SERVER_WORKERS=4
BCRYPT_ROUNDS=12 BCRYPT_ROUNDS=12
@ -39,7 +41,7 @@ FILESYSTEM_DISK=local
QUEUE_CONNECTION=database QUEUE_CONNECTION=database
CACHE_STORE=database CACHE_STORE=database
CACHE_PREFIX= # CACHE_PREFIX=
MEMCACHED_HOST=127.0.0.1 MEMCACHED_HOST=127.0.0.1
@ -49,6 +51,7 @@ REDIS_PASSWORD=null
REDIS_PORT=6379 REDIS_PORT=6379
MAIL_MAILER=log MAIL_MAILER=log
MAIL_SCHEME=null
MAIL_HOST=127.0.0.1 MAIL_HOST=127.0.0.1
MAIL_PORT=2525 MAIL_PORT=2525
MAIL_USERNAME=null MAIL_USERNAME=null

View file

@ -37,7 +37,7 @@ class ParseCachedWebMentions extends Command
{ {
$htmlFiles = $filesystem->allFiles(storage_path() . '/HTML'); $htmlFiles = $filesystem->allFiles(storage_path() . '/HTML');
foreach ($htmlFiles as $file) { foreach ($htmlFiles as $file) {
if ($file->getExtension() !== 'backup') { //we dont want to parse `.backup` files if ($file->getExtension() !== 'backup') { // we dont want to parse `.backup` files
$filepath = $file->getPathname(); $filepath = $file->getPathname();
$this->info('Loading HTML from: ' . $filepath); $this->info('Loading HTML from: ' . $filepath);
$html = $filesystem->get($filepath); $html = $filesystem->get($filepath);

View file

@ -6,5 +6,5 @@ use Exception;
class RemoteContentNotFoundException extends Exception class RemoteContentNotFoundException extends Exception
{ {
//used when guzzle cant find the remote content // used when guzzle cant find the remote content
} }

View file

@ -30,7 +30,7 @@ class ArticlesController extends Controller
public function store(): RedirectResponse public function store(): RedirectResponse
{ {
//if a `.md` is attached use that for the main content. // if a `.md` is attached use that for the main content.
if (request()->hasFile('article')) { if (request()->hasFile('article')) {
$file = request()->file('article')->openFile(); $file = request()->file('article')->openFile();
$content = $file->fread($file->getSize()); $content = $file->fread($file->getSize());

View file

@ -67,7 +67,7 @@ class NotesController extends Controller
*/ */
public function update(int $noteId): RedirectResponse public function update(int $noteId): RedirectResponse
{ {
//update note data // update note data
$note = Note::findOrFail($noteId); $note = Note::findOrFail($noteId);
$note->note = request()->input('content'); $note->note = request()->input('content');
$note->in_reply_to = request()->input('in-reply-to'); $note->in_reply_to = request()->input('in-reply-to');

View file

@ -26,8 +26,8 @@ class IndieAuthController extends Controller
'authorization_endpoint' => route('indieauth.start'), 'authorization_endpoint' => route('indieauth.start'),
'token_endpoint' => route('indieauth.token'), 'token_endpoint' => route('indieauth.token'),
'code_challenge_methods_supported' => ['S256'], 'code_challenge_methods_supported' => ['S256'],
//'introspection_endpoint' => route('indieauth.introspection'), // 'introspection_endpoint' => route('indieauth.introspection'),
//'introspection_endpoint_auth_methods_supported' => ['none'], // 'introspection_endpoint_auth_methods_supported' => ['none'],
]); ]);
} }

View file

@ -191,7 +191,7 @@ class MicropubMediaController extends Controller
*/ */
private function getFileTypeFromMimeType(string $mimeType): string private function getFileTypeFromMimeType(string $mimeType): string
{ {
//try known images // try known images
$imageMimeTypes = [ $imageMimeTypes = [
'image/gif', 'image/gif',
'image/jpeg', 'image/jpeg',
@ -203,7 +203,7 @@ class MicropubMediaController extends Controller
if (in_array($mimeType, $imageMimeTypes)) { if (in_array($mimeType, $imageMimeTypes)) {
return 'image'; return 'image';
} }
//try known video // try known video
$videoMimeTypes = [ $videoMimeTypes = [
'video/mp4', 'video/mp4',
'video/mpeg', 'video/mpeg',
@ -214,7 +214,7 @@ class MicropubMediaController extends Controller
if (in_array($mimeType, $videoMimeTypes)) { if (in_array($mimeType, $videoMimeTypes)) {
return 'video'; return 'video';
} }
//try known audio types // try known audio types
$audioMimeTypes = [ $audioMimeTypes = [
'audio/midi', 'audio/midi',
'audio/mpeg', 'audio/mpeg',

View file

@ -33,7 +33,7 @@ class WebMentionsController extends Controller
*/ */
public function receive(Request $request): Response public function receive(Request $request): Response
{ {
//first we trivially reject requests that lack all required inputs // first we trivially reject requests that lack all required inputs
if (($request->has('target') !== true) || ($request->has('source') !== true)) { if (($request->has('target') !== true) || ($request->has('source') !== true)) {
return response( return response(
'You need both the target and source parameters', 'You need both the target and source parameters',
@ -41,12 +41,12 @@ class WebMentionsController extends Controller
); );
} }
//next check the $target is valid // next check the $target is valid
$path = parse_url($request->input('target'), PHP_URL_PATH); $path = parse_url($request->input('target'), PHP_URL_PATH);
$pathParts = explode('/', $path); $pathParts = explode('/', $path);
if ($pathParts[1] === 'notes') { if ($pathParts[1] === 'notes') {
//we have a note // we have a note
$noteId = $pathParts[2]; $noteId = $pathParts[2];
try { try {
$note = Note::findOrFail(resolve(Numbers::class)->b60tonum($noteId)); $note = Note::findOrFail(resolve(Numbers::class)->b60tonum($noteId));

View file

@ -35,30 +35,30 @@ class DownloadWebMention implements ShouldQueue
public function handle(Client $guzzle): void public function handle(Client $guzzle): void
{ {
$response = $guzzle->request('GET', $this->source); $response = $guzzle->request('GET', $this->source);
//4XX and 5XX responses should get Guzzle to throw an exception, // 4XX and 5XX responses should get Guzzle to throw an exception,
//Laravel should catch and retry these automatically. // Laravel should catch and retry these automatically.
if ($response->getStatusCode() === 200) { if ($response->getStatusCode() === 200) {
$filesystem = new FileSystem; $filesystem = new FileSystem;
$filename = storage_path('HTML') . '/' . $this->createFilenameFromURL($this->source); $filename = storage_path('HTML') . '/' . $this->createFilenameFromURL($this->source);
//backup file first // backup file first
$filenameBackup = $filename . '.' . date('Y-m-d') . '.backup'; $filenameBackup = $filename . '.' . date('Y-m-d') . '.backup';
if ($filesystem->exists($filename)) { if ($filesystem->exists($filename)) {
$filesystem->copy($filename, $filenameBackup); $filesystem->copy($filename, $filenameBackup);
} }
//check if base directory exists // check if base directory exists
if (! $filesystem->exists($filesystem->dirname($filename))) { if (! $filesystem->exists($filesystem->dirname($filename))) {
$filesystem->makeDirectory( $filesystem->makeDirectory(
$filesystem->dirname($filename), $filesystem->dirname($filename),
0755, //mode 0755, // mode
true //recursive true // recursive
); );
} }
//save new HTML // save new HTML
$filesystem->put( $filesystem->put(
$filename, $filename,
(string) $response->getBody() (string) $response->getBody()
); );
//remove backup if the same // remove backup if the same
if ($filesystem->exists($filenameBackup)) { if ($filesystem->exists($filenameBackup)) {
if ($filesystem->get($filename) === $filesystem->get($filenameBackup)) { if ($filesystem->get($filename) === $filesystem->get($filenameBackup)) {
$filesystem->delete($filenameBackup); $filesystem->delete($filenameBackup);

View file

@ -49,7 +49,7 @@ class ProcessLike implements ShouldQueue
$this->like->content = $tweet->html; $this->like->content = $tweet->html;
$this->like->save(); $this->like->save();
//POSSE like // POSSE like
try { try {
$client->request( $client->request(
'POST', 'POST',

View file

@ -32,18 +32,21 @@ class ProcessMedia implements ShouldQueue
*/ */
public function handle(ImageManager $manager): void public function handle(ImageManager $manager): void
{ {
// Load file
$file = Storage::disk('local')->get('media/' . $this->filename);
// Open file // Open file
try { try {
$image = $manager->read(storage_path('app/media/') . $this->filename); $image = $manager->read($file);
} catch (DecoderException) { } catch (DecoderException) {
// not an image; delete file and end job // not an image; delete file and end job
unlink(storage_path('app/media/') . $this->filename); Storage::disk('local')->delete('media/' . $this->filename);
return; return;
} }
// Save the file publicly // Save the file publicly
Storage::disk('local')->copy('media/' . $this->filename, 'public/media/' . $this->filename); Storage::disk('public')->put('media/' . $this->filename, $file);
// Create smaller versions if necessary // Create smaller versions if necessary
if ($image->width() > 1000) { if ($image->width() > 1000) {
@ -54,13 +57,13 @@ class ProcessMedia implements ShouldQueue
$basename = trim(implode('.', $filenameParts), '.'); $basename = trim(implode('.', $filenameParts), '.');
$medium = $image->resize(width: 1000); $medium = $image->resize(width: 1000);
Storage::disk('local')->put('public/media/' . $basename . '-medium.' . $extension, (string) $medium->encode()); Storage::disk('public')->put('media/' . $basename . '-medium.' . $extension, (string) $medium->encode());
$small = $image->resize(width: 500); $small = $image->resize(width: 500);
Storage::disk('local')->put('public/media/' . $basename . '-small.' . $extension, (string) $small->encode()); Storage::disk('public')->put('media/' . $basename . '-small.' . $extension, (string) $small->encode());
} }
// Now we can delete the locally saved image // Now we can delete the locally saved image
unlink(storage_path('app/media/') . $this->filename); Storage::disk('local')->delete('media/' . $this->filename);
} }
} }

View file

@ -49,7 +49,7 @@ class SaveProfileImage implements ShouldQueue
$home = array_shift($home); $home = array_shift($home);
} }
//dont save pbs.twimg.com links // dont save pbs.twimg.com links
if ( if (
$photo $photo
&& parse_url($photo, PHP_URL_HOST) !== 'pbs.twimg.com' && parse_url($photo, PHP_URL_HOST) !== 'pbs.twimg.com'

View file

@ -72,7 +72,7 @@ class SendWebMentions implements ShouldQueue
$guzzle = resolve(Client::class); $guzzle = resolve(Client::class);
$response = $guzzle->get($url); $response = $guzzle->get($url);
//check HTTP Headers for webmention endpoint // check HTTP Headers for webmention endpoint
$links = Header::parse($response->getHeader('Link')); $links = Header::parse($response->getHeader('Link'));
foreach ($links as $link) { foreach ($links as $link) {
if (array_key_exists('rel', $link) && mb_stristr($link['rel'], 'webmention')) { if (array_key_exists('rel', $link) && mb_stristr($link['rel'], 'webmention')) {
@ -80,7 +80,7 @@ class SendWebMentions implements ShouldQueue
} }
} }
//failed to find a header so parse HTML // failed to find a header so parse HTML
$html = (string) $response->getBody(); $html = (string) $response->getBody();
$mf2 = new \Mf2\Parser($html, $url); $mf2 = new \Mf2\Parser($html, $url);

View file

@ -111,7 +111,7 @@ class Note extends Model
{ {
if ($value !== null) { if ($value !== null) {
$normalized = normalizer_normalize($value, Normalizer::FORM_C); $normalized = normalizer_normalize($value, Normalizer::FORM_C);
if ($normalized === '') { //we dont want to save empty strings to the db if ($normalized === '') { // we dont want to save empty strings to the db
$normalized = null; $normalized = null;
} }
$this->attributes['note'] = $normalized; $this->attributes['note'] = $normalized;

View file

@ -59,7 +59,7 @@ class Place extends Model
* sin(radians(places.latitude))))"; * sin(radians(places.latitude))))";
return $query return $query
->select() //pick the columns you want here. ->select() // pick the columns you want here.
->selectRaw("{$haversine} AS distance") ->selectRaw("{$haversine} AS distance")
->whereRaw("{$haversine} < ?", [$distance]); ->whereRaw("{$haversine} < ?", [$distance]);
} }

View file

@ -123,7 +123,7 @@ class WebMention extends Model
$host = parse_url($url, PHP_URL_HOST); $host = parse_url($url, PHP_URL_HOST);
if ($host === 'pbs.twimg.com') { if ($host === 'pbs.twimg.com') {
//make sure we use HTTPS, we know twitter supports it // make sure we use HTTPS, we know twitter supports it
return str_replace('http://', 'https://', $url); return str_replace('http://', 'https://', $url);
} }
@ -135,7 +135,7 @@ class WebMention extends Model
$codebird = resolve(Codebird::class); $codebird = resolve(Codebird::class);
$info = $codebird->users_show(['screen_name' => $username]); $info = $codebird->users_show(['screen_name' => $username]);
$profile_image = $info->profile_image_url_https; $profile_image = $info->profile_image_url_https;
Cache::put($url, $profile_image, 10080); //1 week Cache::put($url, $profile_image, 10080); // 1 week
return $profile_image; return $profile_image;
} }

View file

@ -21,7 +21,7 @@ class BookmarkService extends Service
public function create(array $request, ?string $client = null): Bookmark public function create(array $request, ?string $client = null): Bookmark
{ {
if (Arr::get($request, 'properties.bookmark-of.0')) { if (Arr::get($request, 'properties.bookmark-of.0')) {
//micropub request // micropub request
$url = normalize_url(Arr::get($request, 'properties.bookmark-of.0')); $url = normalize_url(Arr::get($request, 'properties.bookmark-of.0'));
$name = Arr::get($request, 'properties.name.0'); $name = Arr::get($request, 'properties.name.0');
$content = Arr::get($request, 'properties.content.0'); $content = Arr::get($request, 'properties.content.0');
@ -61,7 +61,7 @@ class BookmarkService extends Service
try { try {
$response = $client->request('GET', 'https://web.archive.org/save/' . $url); $response = $client->request('GET', 'https://web.archive.org/save/' . $url);
} catch (ClientException $e) { } catch (ClientException $e) {
//throw an exception to be caught // throw an exception to be caught
throw new InternetArchiveException; throw new InternetArchiveException;
} }
if ($response->hasHeader('Content-Location')) { if ($response->hasHeader('Content-Location')) {
@ -70,7 +70,7 @@ class BookmarkService extends Service
} }
} }
//throw an exception to be caught // throw an exception to be caught
throw new InternetArchiveException; throw new InternetArchiveException;
} }
} }

View file

@ -16,7 +16,7 @@ class LikeService extends Service
public function create(array $request, ?string $client = null): Like public function create(array $request, ?string $client = null): Like
{ {
if (Arr::get($request, 'properties.like-of.0')) { if (Arr::get($request, 'properties.like-of.0')) {
//micropub request // micropub request
$url = normalize_url(Arr::get($request, 'properties.like-of.0')); $url = normalize_url(Arr::get($request, 'properties.like-of.0'));
} }
if (Arr::get($request, 'like-of')) { if (Arr::get($request, 'like-of')) {

View file

@ -20,7 +20,7 @@ class UpdateService
{ {
$urlPath = parse_url(Arr::get($request, 'url'), PHP_URL_PATH); $urlPath = parse_url(Arr::get($request, 'url'), PHP_URL_PATH);
//is it a note we are updating? // is it a note we are updating?
if (mb_substr($urlPath, 1, 5) !== 'notes') { if (mb_substr($urlPath, 1, 5) !== 'notes') {
return response()->json([ return response()->json([
'error' => 'invalid', 'error' => 'invalid',
@ -37,7 +37,7 @@ class UpdateService
], 404); ], 404);
} }
//got the note, are we dealing with a “replace” request? // got the note, are we dealing with a “replace” request?
if (Arr::get($request, 'replace')) { if (Arr::get($request, 'replace')) {
foreach (Arr::get($request, 'replace') as $property => $value) { foreach (Arr::get($request, 'replace') as $property => $value) {
if ($property === 'content') { if ($property === 'content') {
@ -64,7 +64,7 @@ class UpdateService
]); ]);
} }
//how about “add” // how about “add”
if (Arr::get($request, 'add')) { if (Arr::get($request, 'add')) {
foreach (Arr::get($request, 'add') as $property => $value) { foreach (Arr::get($request, 'add') as $property => $value) {
if ($property === 'syndication') { if ($property === 'syndication') {

View file

@ -14,8 +14,8 @@ class PlaceService
*/ */
public function createPlace(array $data): Place public function createPlace(array $data): Place
{ {
//obviously a place needs a lat/lng, but this could be sent in a geo-url // obviously a place needs a lat/lng, but this could be sent in a geo-url
//if no geo array key, we assume the array already has lat/lng values // if no geo array key, we assume the array already has lat/lng values
if (array_key_exists('geo', $data) && $data['geo'] !== null) { if (array_key_exists('geo', $data) && $data['geo'] !== null) {
preg_match_all( preg_match_all(
'/([0-9\.\-]+)/', '/([0-9\.\-]+)/',
@ -40,7 +40,7 @@ class PlaceService
*/ */
public function createPlaceFromCheckin(array $checkin): Place public function createPlaceFromCheckin(array $checkin): Place
{ {
//check if the place exists if from swarm // check if the place exists if from swarm
if (Arr::has($checkin, 'properties.url')) { if (Arr::has($checkin, 'properties.url')) {
$place = Place::whereExternalURL(Arr::get($checkin, 'properties.url.0'))->get(); $place = Place::whereExternalURL(Arr::get($checkin, 'properties.url.0'))->get();
if (count($place) === 1) { if (count($place) === 1) {

View file

@ -1,7 +1,8 @@
{ {
"$schema": "https://getcomposer.org/schema.json",
"name": "jonnybarnes/jonnybarnes.uk", "name": "jonnybarnes/jonnybarnes.uk",
"type": "project", "type": "project",
"description": "The code for jonnybarnes.uk, based on Laravel 10", "description": "The code for jonnybarnes.uk, based on Laravel 11",
"keywords": ["laravel", "framework", "indieweb"], "keywords": ["laravel", "framework", "indieweb"],
"license": "CC0-1.0", "license": "CC0-1.0",
"require": { "require": {
@ -11,14 +12,14 @@
"ext-json": "*", "ext-json": "*",
"ext-pgsql": "*", "ext-pgsql": "*",
"ext-sodium": "*", "ext-sodium": "*",
"cviebrock/eloquent-sluggable": "^11.0", "cviebrock/eloquent-sluggable": "^12.0",
"guzzlehttp/guzzle": "^7.2", "guzzlehttp/guzzle": "^7.2",
"indieauth/client": "^1.1", "indieauth/client": "^1.1",
"intervention/image": "^3", "intervention/image": "^3",
"jonnybarnes/indieweb": "~0.2", "jonnybarnes/indieweb": "~0.2",
"jonnybarnes/webmentions-parser": "~0.5", "jonnybarnes/webmentions-parser": "~0.5",
"jublonet/codebird-php": "4.0.0-beta.1", "jublonet/codebird-php": "4.0.0-beta.1",
"laravel/framework": "^11.0", "laravel/framework": "^12.0",
"laravel/horizon": "^5.0", "laravel/horizon": "^5.0",
"laravel/sanctum": "^4.0", "laravel/sanctum": "^4.0",
"laravel/scout": "^10.1", "laravel/scout": "^10.1",
@ -40,16 +41,15 @@
"barryvdh/laravel-ide-helper": "^3.0", "barryvdh/laravel-ide-helper": "^3.0",
"fakerphp/faker": "^1.9.2", "fakerphp/faker": "^1.9.2",
"laravel/dusk": "^8.0", "laravel/dusk": "^8.0",
"laravel/pail": "^1.2",
"laravel/pint": "^1.0", "laravel/pint": "^1.0",
"laravel/sail": "^1.18", "laravel/sail": "^1.18",
"mockery/mockery": "^1.4.4", "mockery/mockery": "^1.4.4",
"nunomaduro/collision": "^8.1", "nunomaduro/collision": "^8.1",
"openai-php/client": "^0.10.1", "openai-php/client": "^0.10.1",
"phpunit/php-code-coverage": "^10.0", "phpunit/php-code-coverage": "^11.0",
"phpunit/phpunit": "^10.1", "phpunit/phpunit": "^11.0",
"psalm/plugin-laravel": "^2.8", "spatie/laravel-ray": "^1.12"
"spatie/laravel-ray": "^1.12",
"vimeo/psalm": "^5.0"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
@ -78,7 +78,13 @@
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\"" "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
], ],
"post-create-project-cmd": [ "post-create-project-cmd": [
"@php artisan key:generate --ansi" "@php artisan key:generate --ansi",
"@php -r \"file_exists('database/database.sqlite') || touch('database/database.sqlite');\"",
"@php artisan migrate --graceful --ansi"
],
"dev": [
"Composer\\Config::disableProcessTimeout",
"npx concurrently -c \"#93c5fd,#c4b5fd,#fb7185,#fdba74\" \"php artisan serve\" \"php artisan queue:listen --tries=1\" \"php artisan pail --timeout=0\" \"npm run dev\" --names=server,queue,logs,vite"
] ]
}, },
"extra": { "extra": {

3598
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -65,7 +65,7 @@ return [
| |
*/ */
'timezone' => env('APP_TIMEZONE', 'UTC'), 'timezone' => 'UTC',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------

View file

@ -37,6 +37,9 @@ return [
'database' => env('DB_DATABASE', database_path('database.sqlite')), 'database' => env('DB_DATABASE', database_path('database.sqlite')),
'prefix' => '', 'prefix' => '',
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
'busy_timeout' => null,
'journal_mode' => null,
'synchronous' => null,
], ],
'mysql' => [ 'mysql' => [
@ -145,6 +148,7 @@ return [
'options' => [ 'options' => [
'cluster' => env('REDIS_CLUSTER', 'redis'), 'cluster' => env('REDIS_CLUSTER', 'redis'),
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'), 'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
'persistent' => env('REDIS_PERSISTENT', false),
], ],
'default' => [ 'default' => [

View file

@ -119,7 +119,7 @@ return [
'full_log' => false, 'full_log' => false,
], ],
'views' => [ 'views' => [
'data' => false, //Note: Can slow down the application, because the data can be quite large.. 'data' => false, // Note: Can slow down the application, because the data can be quite large..
], ],
'route' => [ 'route' => [
'label' => true, // show complete route on bar 'label' => true, // show complete route on bar

View file

@ -32,8 +32,10 @@ return [
'local' => [ 'local' => [
'driver' => 'local', 'driver' => 'local',
'root' => storage_path('app'), 'root' => storage_path('app/private'),
'serve' => true,
'throw' => false, 'throw' => false,
'report' => false,
], ],
'public' => [ 'public' => [
@ -42,6 +44,7 @@ return [
'url' => env('APP_URL').'/storage', 'url' => env('APP_URL').'/storage',
'visibility' => 'public', 'visibility' => 'public',
'throw' => false, 'throw' => false,
'report' => false,
], ],
's3' => [ 's3' => [
@ -54,6 +57,7 @@ return [
'endpoint' => env('AWS_ENDPOINT'), 'endpoint' => env('AWS_ENDPOINT'),
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
'throw' => false, 'throw' => false,
'report' => false,
], ],
], ],

View file

@ -38,14 +38,14 @@ return [
'smtp' => [ 'smtp' => [
'transport' => 'smtp', 'transport' => 'smtp',
'scheme' => env('MAIL_SCHEME'),
'url' => env('MAIL_URL'), 'url' => env('MAIL_URL'),
'host' => env('MAIL_HOST', '127.0.0.1'), 'host' => env('MAIL_HOST', '127.0.0.1'),
'port' => env('MAIL_PORT', 2525), 'port' => env('MAIL_PORT', 2525),
'encryption' => env('MAIL_ENCRYPTION', 'tls'),
'username' => env('MAIL_USERNAME'), 'username' => env('MAIL_USERNAME'),
'password' => env('MAIL_PASSWORD'), 'password' => env('MAIL_PASSWORD'),
'timeout' => null, 'timeout' => null,
'local_domain' => env('MAIL_EHLO_DOMAIN'), 'local_domain' => env('MAIL_EHLO_DOMAIN', parse_url(env('APP_URL', 'http://localhost'), PHP_URL_HOST)),
], ],
'ses' => [ 'ses' => [

View file

@ -32,7 +32,7 @@ return [
| |
*/ */
'lifetime' => env('SESSION_LIFETIME', 120), 'lifetime' => (int) env('SESSION_LIFETIME', 120),
'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false), 'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false),

View file

@ -83,7 +83,7 @@ class NotesTableSeeder extends Seeder
->where('id', $noteWithoutContact->id) ->where('id', $noteWithoutContact->id)
->update(['updated_at' => $now->toDateTimeString()]); ->update(['updated_at' => $now->toDateTimeString()]);
//copy aarons profile pic in place // copy aarons profile pic in place
$spl = new SplFileInfo(public_path() . '/assets/profile-images/aaronparecki.com'); $spl = new SplFileInfo(public_path() . '/assets/profile-images/aaronparecki.com');
if ($spl->isDir() === false) { if ($spl->isDir() === false) {
mkdir(public_path() . '/assets/profile-images/aaronparecki.com', 0755); mkdir(public_path() . '/assets/profile-images/aaronparecki.com', 0755);

View file

@ -138,7 +138,7 @@ if (! function_exists('normalize_url')) {
$url['query'] = ''; $url['query'] = '';
sort($queries); sort($queries);
foreach ($queries as $query) { foreach ($queries as $query) {
//lets drop query params we dont want // lets drop query params we dont want
$key = stristr($query, '=', true); $key = stristr($query, '=', true);
if (queryKeyIsBanned($key) === false) { if (queryKeyIsBanned($key) === false) {
$url['query'] .= "{$query}&"; $url['query'] .= "{$query}&";
@ -197,7 +197,7 @@ if (! function_exists('prettyPrintJson')) {
case '{': case '{':
case '[': case '[':
$level++; $level++;
//no break // no break
case ',': case ',':
$ends_line_level = $level; $ends_line_level = $level;
break; break;

380
package-lock.json generated
View file

@ -14,11 +14,11 @@
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.6.0", "@eslint/js": "^9.6.0",
"@stylistic/eslint-plugin": "^2.3.0", "@stylistic/eslint-plugin": "^3.0.0",
"eslint": "^9.7.0", "eslint": "^9.7.0",
"globals": "^15.8.0", "globals": "^15.8.0",
"stylelint": "^16.7.0", "stylelint": "^16.7.0",
"stylelint-config-standard": "^36.0.1" "stylelint-config-standard": "^37.0.0"
} }
}, },
"node_modules/@11ty/is-land": { "node_modules/@11ty/is-land": {
@ -200,13 +200,13 @@
} }
}, },
"node_modules/@eslint/config-array": { "node_modules/@eslint/config-array": {
"version": "0.19.0", "version": "0.19.1",
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz",
"integrity": "sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==", "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@eslint/object-schema": "^2.1.4", "@eslint/object-schema": "^2.1.5",
"debug": "^4.3.1", "debug": "^4.3.1",
"minimatch": "^3.1.2" "minimatch": "^3.1.2"
}, },
@ -239,11 +239,14 @@
} }
}, },
"node_modules/@eslint/core": { "node_modules/@eslint/core": {
"version": "0.9.0", "version": "0.10.0",
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz",
"integrity": "sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==", "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": {
"@types/json-schema": "^7.0.15"
},
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
} }
@ -310,9 +313,9 @@
} }
}, },
"node_modules/@eslint/js": { "node_modules/@eslint/js": {
"version": "9.16.0", "version": "9.19.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.16.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz",
"integrity": "sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==", "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -320,9 +323,9 @@
} }
}, },
"node_modules/@eslint/object-schema": { "node_modules/@eslint/object-schema": {
"version": "2.1.4", "version": "2.1.5",
"resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz",
"integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"engines": { "engines": {
@ -330,12 +333,13 @@
} }
}, },
"node_modules/@eslint/plugin-kit": { "node_modules/@eslint/plugin-kit": {
"version": "0.2.3", "version": "0.2.5",
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz",
"integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@eslint/core": "^0.10.0",
"levn": "^0.4.1" "levn": "^0.4.1"
}, },
"engines": { "engines": {
@ -408,6 +412,16 @@
"url": "https://github.com/sponsors/nzakas" "url": "https://github.com/sponsors/nzakas"
} }
}, },
"node_modules/@keyv/serialize": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.0.2.tgz",
"integrity": "sha512-+E/LyaAeuABniD/RvUezWVXKpeuvwLEA9//nE9952zBaOdBd2mQ3pPoM8cUe2X6IcMByfuSLzmYqnYshG60+HQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"buffer": "^6.0.3"
}
},
"node_modules/@nodelib/fs.scandir": { "node_modules/@nodelib/fs.scandir": {
"version": "2.1.5", "version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@ -447,13 +461,13 @@
} }
}, },
"node_modules/@stylistic/eslint-plugin": { "node_modules/@stylistic/eslint-plugin": {
"version": "2.11.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.11.0.tgz", "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-3.0.0.tgz",
"integrity": "sha512-PNRHbydNG5EH8NK4c+izdJlxajIR6GxcUhzsYNRsn6Myep4dsZt0qFCz3rCPnkvgO5FYibDcMqgNHUT+zvjYZw==", "integrity": "sha512-9GJI6iBtGjOqSsyCKUvE6Vn7qDT52hbQaoq/SwxH6A1bciymZfvBfHIIrD3E7Koi2sjzOa/MNQ2XOguHtVJOyw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/utils": "^8.13.0", "@typescript-eslint/utils": "8.13.0",
"eslint-visitor-keys": "^4.2.0", "eslint-visitor-keys": "^4.2.0",
"espree": "^10.3.0", "espree": "^10.3.0",
"estraverse": "^5.3.0", "estraverse": "^5.3.0",
@ -481,14 +495,14 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "8.16.0", "version": "8.13.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.16.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.13.0.tgz",
"integrity": "sha512-mwsZWubQvBki2t5565uxF0EYvG+FwdFb8bMtDuGQLdCCnGPrDEDvm1gtfynuKlnpzeBRqdFCkMf9jg1fnAK8sg==", "integrity": "sha512-XsGWww0odcUT0gJoBZ1DeulY1+jkaHUciUq4jKNv4cpInbvvrtDoyBH9rE/n2V29wQJPk8iCH1wipra9BhmiMA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.16.0", "@typescript-eslint/types": "8.13.0",
"@typescript-eslint/visitor-keys": "8.16.0" "@typescript-eslint/visitor-keys": "8.13.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -499,9 +513,9 @@
} }
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "8.16.0", "version": "8.13.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.16.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.13.0.tgz",
"integrity": "sha512-NzrHj6thBAOSE4d9bsuRNMvk+BvaQvmY4dDglgkgGC0EW/tB3Kelnp3tAKH87GEwzoxgeQn9fNGRyFJM/xd+GQ==", "integrity": "sha512-4cyFErJetFLckcThRUFdReWJjVsPCqyBlJTi6IDEpc1GWCIIZRFxVppjWLIMcQhNGhdWJJRYFHpHoDWvMlDzng==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -513,14 +527,14 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "8.16.0", "version": "8.13.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.16.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.13.0.tgz",
"integrity": "sha512-E2+9IzzXMc1iaBy9zmo+UYvluE3TW7bCGWSF41hVWUE01o8nzr1rvOQYSxelxr6StUvRcTMe633eY8mXASMaNw==", "integrity": "sha512-v7SCIGmVsRK2Cy/LTLGN22uea6SaUIlpBcO/gnMGT/7zPtxp90bphcGf4fyrCQl3ZtiBKqVTG32hb668oIYy1g==",
"dev": true, "dev": true,
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.16.0", "@typescript-eslint/types": "8.13.0",
"@typescript-eslint/visitor-keys": "8.16.0", "@typescript-eslint/visitor-keys": "8.13.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@ -542,16 +556,16 @@
} }
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "8.16.0", "version": "8.13.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.16.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.13.0.tgz",
"integrity": "sha512-C1zRy/mOL8Pj157GiX4kaw7iyRLKfJXBR3L82hk5kS/GyHcOFmy4YUq/zfZti72I9wnuQtA/+xzft4wCC8PJdA==", "integrity": "sha512-A1EeYOND6Uv250nybnLZapeXpYMl8tkzYUxqmoKAWnI4sei3ihf2XdZVd+vVOmHGcp3t+P7yRrNsyyiXTvShFQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.4.0", "@eslint-community/eslint-utils": "^4.4.0",
"@typescript-eslint/scope-manager": "8.16.0", "@typescript-eslint/scope-manager": "8.13.0",
"@typescript-eslint/types": "8.16.0", "@typescript-eslint/types": "8.13.0",
"@typescript-eslint/typescript-estree": "8.16.0" "@typescript-eslint/typescript-estree": "8.13.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -562,22 +576,17 @@
}, },
"peerDependencies": { "peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0" "eslint": "^8.57.0 || ^9.0.0"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "8.16.0", "version": "8.13.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.16.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.13.0.tgz",
"integrity": "sha512-pq19gbaMOmFE3CbL0ZB8J8BFCo2ckfHBfaIsaOZgBIF4EoISJIdLX5xRhd0FGB0LlHReNRuzoJoMGpTjq8F2CQ==", "integrity": "sha512-7N/+lztJqH4Mrf0lb10R/CbI1EaAMMGyF5y0oJvFoAhafwgiRA7TXyd8TFn8FC8k5y2dTsYogg238qavRGNnlw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.16.0", "@typescript-eslint/types": "8.13.0",
"eslint-visitor-keys": "^4.2.0" "eslint-visitor-keys": "^3.4.3"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -587,10 +596,23 @@
"url": "https://opencollective.com/typescript-eslint" "url": "https://opencollective.com/typescript-eslint"
} }
}, },
"node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
"integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
"dev": true,
"license": "Apache-2.0",
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
}
},
"node_modules/@zachleat/snow-fall": { "node_modules/@zachleat/snow-fall": {
"version": "1.0.2", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/@zachleat/snow-fall/-/snow-fall-1.0.2.tgz", "resolved": "https://registry.npmjs.org/@zachleat/snow-fall/-/snow-fall-1.0.3.tgz",
"integrity": "sha512-nyNeliowryq+roSMktyV3o14DduSuU4BvBzruVSPV6e8U8Eid2zNzSj1AzCQByPId7Q4MrIP2QWL2UHeHGfmcA==", "integrity": "sha512-Y9srRbmO+k31vSm+eINYRV9DRoeWGV5/hlAn9o34bLpoWo+T5945v6XGBrFzQYjhyEGB4j/4zXuTW1zTxp2Reg==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/acorn": { "node_modules/acorn": {
@ -693,6 +715,27 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT"
},
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
@ -716,6 +759,52 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/buffer": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT",
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.2.1"
}
},
"node_modules/cacheable": {
"version": "1.8.8",
"resolved": "https://registry.npmjs.org/cacheable/-/cacheable-1.8.8.tgz",
"integrity": "sha512-OE1/jlarWxROUIpd0qGBSKFLkNsotY8pt4GeiVErUYh/NUeTNrT+SBksUgllQv4m6a0W/VZsLuiHb88maavqEw==",
"dev": true,
"license": "MIT",
"dependencies": {
"hookified": "^1.7.0",
"keyv": "^5.2.3"
}
},
"node_modules/cacheable/node_modules/keyv": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-5.2.3.tgz",
"integrity": "sha512-AGKecUfzrowabUv0bH1RIR5Vf7w+l4S3xtQAypKaUpTdIR1EbrAcTxHCrpo9Q+IWeUlFE2palRtgIQcgm+PQJw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@keyv/serialize": "^1.0.2"
}
},
"node_modules/callsites": { "node_modules/callsites": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@ -830,13 +919,13 @@
} }
}, },
"node_modules/css-tree": { "node_modules/css-tree": {
"version": "3.0.1", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.0.1.tgz", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz",
"integrity": "sha512-8Fxxv+tGhORlshCdCwnNJytvlvq46sOLSYEx2ZIGurahWvMucSRnyjPA3AmrMq4VPRYbHVpWj5VkiVasrM2H4Q==", "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"mdn-data": "2.12.1", "mdn-data": "2.12.2",
"source-map-js": "^1.0.1" "source-map-js": "^1.0.1"
}, },
"engines": { "engines": {
@ -857,9 +946,9 @@
} }
}, },
"node_modules/debug": { "node_modules/debug": {
"version": "4.3.7", "version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -935,19 +1024,19 @@
} }
}, },
"node_modules/eslint": { "node_modules/eslint": {
"version": "9.16.0", "version": "9.19.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.16.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz",
"integrity": "sha512-whp8mSQI4C8VXd+fLgSM0lh3UlmcFtVwUQjyKCFfsp+2ItAIYhlq/hqGahGqHE6cv9unM41VlqKk2VtKYR2TaA==", "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1", "@eslint-community/regexpp": "^4.12.1",
"@eslint/config-array": "^0.19.0", "@eslint/config-array": "^0.19.0",
"@eslint/core": "^0.9.0", "@eslint/core": "^0.10.0",
"@eslint/eslintrc": "^3.2.0", "@eslint/eslintrc": "^3.2.0",
"@eslint/js": "9.16.0", "@eslint/js": "9.19.0",
"@eslint/plugin-kit": "^0.2.3", "@eslint/plugin-kit": "^0.2.5",
"@humanfs/node": "^0.16.6", "@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.4.1", "@humanwhocodes/retry": "^0.4.1",
@ -955,7 +1044,7 @@
"@types/json-schema": "^7.0.15", "@types/json-schema": "^7.0.15",
"ajv": "^6.12.4", "ajv": "^6.12.4",
"chalk": "^4.0.0", "chalk": "^4.0.0",
"cross-spawn": "^7.0.5", "cross-spawn": "^7.0.6",
"debug": "^4.3.2", "debug": "^4.3.2",
"escape-string-regexp": "^4.0.0", "escape-string-regexp": "^4.0.0",
"eslint-scope": "^8.2.0", "eslint-scope": "^8.2.0",
@ -1120,9 +1209,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/fast-glob": { "node_modules/fast-glob": {
"version": "3.3.2", "version": "3.3.3",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
"integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -1130,7 +1219,7 @@
"@nodelib/fs.walk": "^1.2.3", "@nodelib/fs.walk": "^1.2.3",
"glob-parent": "^5.1.2", "glob-parent": "^5.1.2",
"merge2": "^1.3.0", "merge2": "^1.3.0",
"micromatch": "^4.0.4" "micromatch": "^4.0.8"
}, },
"engines": { "engines": {
"node": ">=8.6.0" "node": ">=8.6.0"
@ -1164,10 +1253,20 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/fast-uri": { "node_modules/fast-uri": {
"version": "3.0.3", "version": "3.0.6",
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz",
"integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==",
"dev": true, "dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
],
"license": "BSD-3-Clause" "license": "BSD-3-Clause"
}, },
"node_modules/fastest-levenshtein": { "node_modules/fastest-levenshtein": {
@ -1181,9 +1280,9 @@
} }
}, },
"node_modules/fastq": { "node_modules/fastq": {
"version": "1.17.1", "version": "1.18.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz",
"integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==",
"dev": true, "dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
@ -1309,9 +1408,9 @@
} }
}, },
"node_modules/globals": { "node_modules/globals": {
"version": "15.12.0", "version": "15.14.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-15.12.0.tgz", "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz",
"integrity": "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==", "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -1359,6 +1458,13 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/hookified": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/hookified/-/hookified-1.7.0.tgz",
"integrity": "sha512-XQdMjqC1AyeOzfs+17cnIk7Wdfu1hh2JtcyNfBf5u9jHrT3iZUlGHxLTntFBuk5lwkqJ6l3+daeQdHK5yByHVA==",
"dev": true,
"license": "MIT"
},
"node_modules/html-tags": { "node_modules/html-tags": {
"version": "3.3.1", "version": "3.3.1",
"resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz",
@ -1372,6 +1478,27 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "BSD-3-Clause"
},
"node_modules/ignore": { "node_modules/ignore": {
"version": "5.3.2", "version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@ -1621,9 +1748,9 @@
} }
}, },
"node_modules/mdn-data": { "node_modules/mdn-data": {
"version": "2.12.1", "version": "2.12.2",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.1.tgz", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz",
"integrity": "sha512-rsfnCbOHjqrhWxwt5/wtSLzpoKTzW7OXdT5lLOIH1OTYhWu9rRJveGq0sKvDZODABH7RX+uoR+DYcpFnq4Tf6Q==", "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==",
"dev": true, "dev": true,
"license": "CC0-1.0" "license": "CC0-1.0"
}, },
@ -1869,9 +1996,9 @@
} }
}, },
"node_modules/postcss": { "node_modules/postcss": {
"version": "8.4.49", "version": "8.5.1",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz",
"integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -1889,7 +2016,7 @@
], ],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"nanoid": "^3.3.7", "nanoid": "^3.3.8",
"picocolors": "^1.1.1", "picocolors": "^1.1.1",
"source-map-js": "^1.2.1" "source-map-js": "^1.2.1"
}, },
@ -2177,9 +2304,9 @@
} }
}, },
"node_modules/stylelint": { "node_modules/stylelint": {
"version": "16.11.0", "version": "16.13.2",
"resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.11.0.tgz", "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.13.2.tgz",
"integrity": "sha512-zrl4IrKmjJQ+h9FoMp69UMCq5SxeHk0URhxUBj4d3ISzo/DplOFBJZc7t7Dr6otB+1bfbbKNLOmCDpzKSlW+Nw==", "integrity": "sha512-wDlgh0mRO9RtSa3TdidqHd0nOG8MmUyVKl+dxA6C1j8aZRzpNeEgdhFmU5y4sZx4Fc6r46p0fI7p1vR5O2DZqA==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -2202,16 +2329,16 @@
"colord": "^2.9.3", "colord": "^2.9.3",
"cosmiconfig": "^9.0.0", "cosmiconfig": "^9.0.0",
"css-functions-list": "^3.2.3", "css-functions-list": "^3.2.3",
"css-tree": "^3.0.1", "css-tree": "^3.1.0",
"debug": "^4.3.7", "debug": "^4.3.7",
"fast-glob": "^3.3.2", "fast-glob": "^3.3.3",
"fastest-levenshtein": "^1.0.16", "fastest-levenshtein": "^1.0.16",
"file-entry-cache": "^9.1.0", "file-entry-cache": "^10.0.5",
"global-modules": "^2.0.0", "global-modules": "^2.0.0",
"globby": "^11.1.0", "globby": "^11.1.0",
"globjoin": "^0.1.4", "globjoin": "^0.1.4",
"html-tags": "^3.3.1", "html-tags": "^3.3.1",
"ignore": "^6.0.2", "ignore": "^7.0.1",
"imurmurhash": "^0.1.4", "imurmurhash": "^0.1.4",
"is-plain-object": "^5.0.0", "is-plain-object": "^5.0.0",
"known-css-properties": "^0.35.0", "known-css-properties": "^0.35.0",
@ -2229,7 +2356,7 @@
"string-width": "^4.2.3", "string-width": "^4.2.3",
"supports-hyperlinks": "^3.1.0", "supports-hyperlinks": "^3.1.0",
"svg-tags": "^1.0.0", "svg-tags": "^1.0.0",
"table": "^6.8.2", "table": "^6.9.0",
"write-file-atomic": "^5.0.1" "write-file-atomic": "^5.0.1"
}, },
"bin": { "bin": {
@ -2240,9 +2367,9 @@
} }
}, },
"node_modules/stylelint-config-recommended": { "node_modules/stylelint-config-recommended": {
"version": "14.0.1", "version": "15.0.0",
"resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.1.tgz", "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-15.0.0.tgz",
"integrity": "sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg==", "integrity": "sha512-9LejMFsat7L+NXttdHdTq94byn25TD+82bzGRiV1Pgasl99pWnwipXS5DguTpp3nP1XjvLXVnEJIuYBfsRjRkA==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -2259,13 +2386,13 @@
"node": ">=18.12.0" "node": ">=18.12.0"
}, },
"peerDependencies": { "peerDependencies": {
"stylelint": "^16.1.0" "stylelint": "^16.13.0"
} }
}, },
"node_modules/stylelint-config-standard": { "node_modules/stylelint-config-standard": {
"version": "36.0.1", "version": "37.0.0",
"resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-36.0.1.tgz", "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-37.0.0.tgz",
"integrity": "sha512-8aX8mTzJ6cuO8mmD5yon61CWuIM4UD8Q5aBcWKGSf6kg+EC3uhB+iOywpTK4ca6ZL7B49en8yanOFtUW0qNzyw==", "integrity": "sha512-+6eBlbSTrOn/il2RlV0zYGQwRTkr+WtzuVSs1reaWGObxnxLpbcspCUYajVQHonVfxVw2U+h42azGhrBvcg8OA==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -2279,13 +2406,13 @@
], ],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"stylelint-config-recommended": "^14.0.1" "stylelint-config-recommended": "^15.0.0"
}, },
"engines": { "engines": {
"node": ">=18.12.0" "node": ">=18.12.0"
}, },
"peerDependencies": { "peerDependencies": {
"stylelint": "^16.1.0" "stylelint": "^16.13.0"
} }
}, },
"node_modules/stylelint/node_modules/balanced-match": { "node_modules/stylelint/node_modules/balanced-match": {
@ -2296,36 +2423,31 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/stylelint/node_modules/file-entry-cache": { "node_modules/stylelint/node_modules/file-entry-cache": {
"version": "9.1.0", "version": "10.0.5",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.1.0.tgz", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-10.0.5.tgz",
"integrity": "sha512-/pqPFG+FdxWQj+/WSuzXSDaNzxgTLr/OrR1QuqfEZzDakpdYE70PwUxL7BPUa8hpjbvY1+qvCl8k+8Tq34xJgg==", "integrity": "sha512-umpQsJrBNsdMDgreSryMEXvJh66XeLtZUwA8Gj7rHGearGufUFv6rB/bcXRFsiGWw/VeSUgUofF4Rf2UKEOrTA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"flat-cache": "^5.0.0" "flat-cache": "^6.1.5"
},
"engines": {
"node": ">=18"
} }
}, },
"node_modules/stylelint/node_modules/flat-cache": { "node_modules/stylelint/node_modules/flat-cache": {
"version": "5.0.0", "version": "6.1.5",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-5.0.0.tgz", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.5.tgz",
"integrity": "sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==", "integrity": "sha512-QR+2kN38f8nMfiIQ1LHYjuDEmZNZVjxuxY+HufbS3BW0EX01Q5OnH7iduOYRutmgiXb797HAKcXUeXrvRjjgSQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"flatted": "^3.3.1", "cacheable": "^1.8.7",
"keyv": "^4.5.4" "flatted": "^3.3.2",
}, "hookified": "^1.6.0"
"engines": {
"node": ">=18"
} }
}, },
"node_modules/stylelint/node_modules/ignore": { "node_modules/stylelint/node_modules/ignore": {
"version": "6.0.2", "version": "7.0.3",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-6.0.2.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.3.tgz",
"integrity": "sha512-InwqeHHN2XpumIkMvpl/DCJVrAHgCsG5+cn1XlnLWGwtZBm8QJfSusItfrwx81CTp5agNZqpKU2J/ccC5nGT4A==", "integrity": "sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -2379,9 +2501,9 @@
"dev": true "dev": true
}, },
"node_modules/table": { "node_modules/table": {
"version": "6.8.2", "version": "6.9.0",
"resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz",
"integrity": "sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==", "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==",
"dev": true, "dev": true,
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
@ -2459,9 +2581,9 @@
} }
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "5.7.2", "version": "5.7.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
"integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true, "peer": true,

View file

@ -7,11 +7,11 @@
"license": "CC0-1.0", "license": "CC0-1.0",
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.6.0", "@eslint/js": "^9.6.0",
"@stylistic/eslint-plugin": "^2.3.0", "@stylistic/eslint-plugin": "^3.0.0",
"eslint": "^9.7.0", "eslint": "^9.7.0",
"globals": "^15.8.0", "globals": "^15.8.0",
"stylelint": "^16.7.0", "stylelint": "^16.7.0",
"stylelint-config-standard": "^36.0.1" "stylelint-config-standard": "^37.0.0"
}, },
"scripts": { "scripts": {
"eslint": "eslint public/assets/js/*.js", "eslint": "eslint public/assets/js/*.js",

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
public/assets/js/app.js.zst Normal file

Binary file not shown.

Binary file not shown.

View file

@ -1,55 +1,20 @@
<?php <?php
use Illuminate\Contracts\Http\Kernel; use Illuminate\Foundation\Application;
use Illuminate\Http\Request; use Illuminate\Http\Request;
define('LARAVEL_START', microtime(true)); define('LARAVEL_START', microtime(true));
/* // Determine if the application is in maintenance mode...
|--------------------------------------------------------------------------
| Check If The Application Is Under Maintenance
|--------------------------------------------------------------------------
|
| If the application is in maintenance / demo mode via the "down" command
| we will load this file so that any pre-rendered content can be shown
| instead of starting the framework, which could cause an exception.
|
*/
if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) { if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) {
require $maintenance; require $maintenance;
} }
/* // Register the Composer autoloader...
|--------------------------------------------------------------------------
| Register The Auto Loader
|--------------------------------------------------------------------------
|
| Composer provides a convenient, automatically generated class loader for
| this application. We just need to utilize it! We'll simply require it
| into the script here so we don't need to manually load our classes.
|
*/
require __DIR__.'/../vendor/autoload.php'; require __DIR__.'/../vendor/autoload.php';
/* // Bootstrap Laravel and handle the request...
|-------------------------------------------------------------------------- /** @var Application $app */
| Run The Application
|--------------------------------------------------------------------------
|
| Once we have the application, we can handle the incoming request using
| the application's HTTP kernel. Then, we will send the response back
| to this client's browser, allowing them to enjoy our application.
|
*/
$app = require_once __DIR__.'/../bootstrap/app.php'; $app = require_once __DIR__.'/../bootstrap/app.php';
$kernel = $app->make(Kernel::class); $app->handleRequest(Request::capture());
$response = $kernel->handle(
$request = Request::capture()
)->send();
$kernel->terminate($request, $response);

View file

@ -64,7 +64,7 @@ Route::domain(config('url.longurl'))->group(function () {
Route::middleware(MyAuthMiddleware::class)->prefix('admin')->group(function () { Route::middleware(MyAuthMiddleware::class)->prefix('admin')->group(function () {
Route::get('/', [HomeController::class, 'welcome']); Route::get('/', [HomeController::class, 'welcome']);
//Articles // Articles
Route::prefix('blog')->group(function () { Route::prefix('blog')->group(function () {
Route::get('/', [AdminArticlesController::class, 'index']); Route::get('/', [AdminArticlesController::class, 'index']);
Route::get('/create', [AdminArticlesController::class, 'create']); Route::get('/create', [AdminArticlesController::class, 'create']);

View file

@ -1,13 +1,41 @@
#!/usr/bin/env zsh #!/usr/bin/env zsh
if ! type fd &> /dev/null; then if ! (( $+commands[fd] )) &> /dev/null; then
echo "fd not installed" echo "fd not installed"
exit 1 exit 1
fi fi
if ! type brotli &> /dev/null; then if ! (( $+commands[brotli] )) &> /dev/null; then
echo "brotli not installed" echo "brotli not installed"
exit 1 exit 1
fi fi
fd -e css -e js --search-path ./public/assets --type f -x brotli --force --best --output={}.br {} if ! (( $+commands[zstd] )) &> /dev/null; then
echo "zstd not installed"
exit 1
fi
# Make .br files
fd --extension css --extension js --search-path ./public/assets --type f --exec brotli --force --best --output={}.br {}
# Make .zst files
fd --extension css --extension js --search-path ./public/assets --type f --exec zstd --quiet --force --ultra -22 --exclude-compressed {} -o {}.zst
# Remove files that actually got bigger!
fd --extension br --extension zst --search-path ./public/assets --type f --exec sh -c '
for file; do
src="${file%.br}"
src="${src%.zst}"
if [ -f "$src" ]; then
# Get file sizes using stat with cross-platform compatibility
if [ "$(uname)" = "Darwin" ]; then
file_size=$(stat -f%z "$file")
src_size=$(stat -f%z "$src")
else
file_size=$(stat -c%s "$file")
src_size=$(stat -c%s "$src")
fi
# Compare sizes and rm compressed file if larger than the source
[ "$file_size" -ge "$src_size" ] && rm "$file"
fi
done
' _ {}

View file

@ -12,7 +12,7 @@ class ExampleTest extends DuskTestCase
* *
* @return void * @return void
*/ */
public function testBasicExample() public function test_basic_example()
{ {
$this->browse(function (Browser $browser) { $this->browse(function (Browser $browser) {
$browser->visit('/') $browser->visit('/')

View file

@ -6,13 +6,14 @@ namespace Tests\Feature\Admin;
use App\Models\User; use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class AdminHomeControllerTest extends TestCase class AdminHomeControllerTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
/** @test */ #[Test]
public function adminHomepageLoads(): void public function adminHomepageLoads(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();

View file

@ -5,25 +5,26 @@ declare(strict_types=1);
namespace Tests\Feature\Admin; namespace Tests\Feature\Admin;
use App\Models\User; use App\Models\User;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class AdminTest extends TestCase class AdminTest extends TestCase
{ {
/** @test */ #[Test]
public function adminPageRedirectsUnauthorisedUsersToLoginPage(): void public function adminPageRedirectsUnauthorisedUsersToLoginPage(): void
{ {
$response = $this->get('/admin'); $response = $this->get('/admin');
$response->assertRedirect('/login'); $response->assertRedirect('/login');
} }
/** @test */ #[Test]
public function loginPageLoads(): void public function loginPageLoads(): void
{ {
$response = $this->get('/login'); $response = $this->get('/login');
$response->assertViewIs('login'); $response->assertViewIs('login');
} }
/** @test */ #[Test]
public function loginAttemptWithBadCredentialsFails(): void public function loginAttemptWithBadCredentialsFails(): void
{ {
$response = $this->post('/login', [ $response = $this->post('/login', [
@ -33,7 +34,7 @@ class AdminTest extends TestCase
$response->assertRedirect('/login'); $response->assertRedirect('/login');
} }
/** @test */ #[Test]
public function loginSucceeds(): void public function loginSucceeds(): void
{ {
User::factory([ User::factory([
@ -49,7 +50,7 @@ class AdminTest extends TestCase
$response->assertRedirect('/admin'); $response->assertRedirect('/admin');
} }
/** @test */ #[Test]
public function whenLoggedInRedirectsToAdminPage(): void public function whenLoggedInRedirectsToAdminPage(): void
{ {
$user = User::factory()->create(); $user = User::factory()->create();
@ -57,14 +58,14 @@ class AdminTest extends TestCase
$response->assertRedirect('/'); $response->assertRedirect('/');
} }
/** @test */ #[Test]
public function loggedOutUsersSimplyRedirected(): void public function loggedOutUsersSimplyRedirected(): void
{ {
$response = $this->get('/logout'); $response = $this->get('/logout');
$response->assertRedirect('/'); $response->assertRedirect('/');
} }
/** @test */ #[Test]
public function loggedInUsersShownLogoutForm(): void public function loggedInUsersShownLogoutForm(): void
{ {
$user = User::factory()->create(); $user = User::factory()->create();
@ -72,7 +73,7 @@ class AdminTest extends TestCase
$response->assertViewIs('logout'); $response->assertViewIs('logout');
} }
/** @test */ #[Test]
public function loggedInUsersCanLogout(): void public function loggedInUsersCanLogout(): void
{ {
$user = User::factory()->create(); $user = User::factory()->create();

View file

@ -9,13 +9,14 @@ use App\Models\User;
use Faker\Factory; use Faker\Factory;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\UploadedFile; use Illuminate\Http\UploadedFile;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class ArticlesTest extends TestCase class ArticlesTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
/** @test */ #[Test]
public function adminArticlesPageLoads(): void public function adminArticlesPageLoads(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -25,7 +26,7 @@ class ArticlesTest extends TestCase
$response->assertSeeText('Select article to edit:'); $response->assertSeeText('Select article to edit:');
} }
/** @test */ #[Test]
public function adminCanLoadFormToCreateArticle(): void public function adminCanLoadFormToCreateArticle(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -35,7 +36,7 @@ class ArticlesTest extends TestCase
$response->assertSeeText('Title (URL)'); $response->assertSeeText('Title (URL)');
} }
/** @test */ #[Test]
public function admiNCanCreateNewArticle(): void public function admiNCanCreateNewArticle(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -48,7 +49,7 @@ class ArticlesTest extends TestCase
$this->assertDatabaseHas('articles', ['title' => 'Test Title']); $this->assertDatabaseHas('articles', ['title' => 'Test Title']);
} }
/** @test */ #[Test]
public function adminCanCreateNewArticleWithFile(): void public function adminCanCreateNewArticleWithFile(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -73,7 +74,7 @@ class ArticlesTest extends TestCase
]); ]);
} }
/** @test */ #[Test]
public function articleCanLoadFormToEditArticle(): void public function articleCanLoadFormToEditArticle(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -86,7 +87,7 @@ class ArticlesTest extends TestCase
$response->assertSeeText('This is *my* new blog. It uses `Markdown`.'); $response->assertSeeText('This is *my* new blog. It uses `Markdown`.');
} }
/** @test */ #[Test]
public function adminCanEditArticle(): void public function adminCanEditArticle(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -104,7 +105,7 @@ class ArticlesTest extends TestCase
]); ]);
} }
/** @test */ #[Test]
public function adminCanDeleteArticle(): void public function adminCanDeleteArticle(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();

View file

@ -7,13 +7,14 @@ namespace Tests\Feature\Admin;
use App\Models\Bio; use App\Models\Bio;
use App\Models\User; use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class BioTest extends TestCase class BioTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
/** @test */ #[Test]
public function adminBiosPageLoads(): void public function adminBiosPageLoads(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -23,7 +24,7 @@ class BioTest extends TestCase
$response->assertSeeText('Edit bio'); $response->assertSeeText('Edit bio');
} }
/** @test */ #[Test]
public function adminCanCreateBio(): void public function adminCanCreateBio(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -36,7 +37,7 @@ class BioTest extends TestCase
$this->assertDatabaseHas('bios', ['content' => 'Bio content']); $this->assertDatabaseHas('bios', ['content' => 'Bio content']);
} }
/** @test */ #[Test]
public function adminCanLoadExistingBio(): void public function adminCanLoadExistingBio(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -49,7 +50,7 @@ class BioTest extends TestCase
$response->assertSeeText('This is <em>my</em> bio. It uses <strong>HTML</strong>.'); $response->assertSeeText('This is <em>my</em> bio. It uses <strong>HTML</strong>.');
} }
/** @test */ #[Test]
public function adminCanEditBio(): void public function adminCanEditBio(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();

View file

@ -7,13 +7,14 @@ namespace Tests\Feature\Admin;
use App\Models\MicropubClient; use App\Models\MicropubClient;
use App\Models\User; use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class ClientsTest extends TestCase class ClientsTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
/** @test */ #[Test]
public function clientsPageLoads(): void public function clientsPageLoads(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -23,7 +24,7 @@ class ClientsTest extends TestCase
$response->assertSeeText('Clients'); $response->assertSeeText('Clients');
} }
/** @test */ #[Test]
public function adminCanLoadFormToCreateClient(): void public function adminCanLoadFormToCreateClient(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -33,7 +34,7 @@ class ClientsTest extends TestCase
$response->assertSeeText('New Client'); $response->assertSeeText('New Client');
} }
/** @test */ #[Test]
public function adminCanCreateNewClient(): void public function adminCanCreateNewClient(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -49,7 +50,7 @@ class ClientsTest extends TestCase
]); ]);
} }
/** @test */ #[Test]
public function adminCanLoadEditFormForClient(): void public function adminCanLoadEditFormForClient(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -62,7 +63,7 @@ class ClientsTest extends TestCase
$response->assertSee('https://jbl5.dev/notes/new'); $response->assertSee('https://jbl5.dev/notes/new');
} }
/** @test */ #[Test]
public function adminCanEditClient(): void public function adminCanEditClient(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -80,7 +81,7 @@ class ClientsTest extends TestCase
]); ]);
} }
/** @test */ #[Test]
public function adminCanDeleteClient(): void public function adminCanDeleteClient(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();

View file

@ -12,6 +12,7 @@ use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response; use GuzzleHttp\Psr7\Response;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\UploadedFile; use Illuminate\Http\UploadedFile;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class ContactsTest extends TestCase class ContactsTest extends TestCase
@ -27,7 +28,7 @@ class ContactsTest extends TestCase
parent::tearDown(); parent::tearDown();
} }
/** @test */ #[Test]
public function contactIndexPageLoads(): void public function contactIndexPageLoads(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -36,7 +37,7 @@ class ContactsTest extends TestCase
$response->assertViewIs('admin.contacts.index'); $response->assertViewIs('admin.contacts.index');
} }
/** @test */ #[Test]
public function contactCreatePageLoads(): void public function contactCreatePageLoads(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -45,7 +46,7 @@ class ContactsTest extends TestCase
$response->assertViewIs('admin.contacts.create'); $response->assertViewIs('admin.contacts.create');
} }
/** @test */ #[Test]
public function adminCanCreateNewContact(): void public function adminCanCreateNewContact(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -62,7 +63,7 @@ class ContactsTest extends TestCase
]); ]);
} }
/** @test */ #[Test]
public function adminCanSeeFormToEditContact(): void public function adminCanSeeFormToEditContact(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -72,7 +73,7 @@ class ContactsTest extends TestCase
$response->assertViewIs('admin.contacts.edit'); $response->assertViewIs('admin.contacts.edit');
} }
/** @test */ #[Test]
public function adminCanUpdateContact(): void public function adminCanUpdateContact(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -91,7 +92,7 @@ class ContactsTest extends TestCase
]); ]);
} }
/** @test */ #[Test]
public function adminCanEditContactAndUploadAvatar(): void public function adminCanEditContactAndUploadAvatar(): void
{ {
copy(__DIR__ . '/../../aaron.png', sys_get_temp_dir() . '/tantek.png'); copy(__DIR__ . '/../../aaron.png', sys_get_temp_dir() . '/tantek.png');
@ -114,7 +115,7 @@ class ContactsTest extends TestCase
); );
} }
/** @test */ #[Test]
public function adminCanDeleteContact(): void public function adminCanDeleteContact(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -132,7 +133,7 @@ class ContactsTest extends TestCase
]); ]);
} }
/** @test */ #[Test]
public function adminCanTriggerRetrievalOfRemoteAvatar(): void public function adminCanTriggerRetrievalOfRemoteAvatar(): void
{ {
$html = <<<'HTML' $html = <<<'HTML'
@ -161,7 +162,7 @@ class ContactsTest extends TestCase
); );
} }
/** @test */ #[Test]
public function gettingRemoteAvatarFailsGracefullyWithRemoteNotFound(): void public function gettingRemoteAvatarFailsGracefullyWithRemoteNotFound(): void
{ {
$mock = new MockHandler([ $mock = new MockHandler([
@ -178,7 +179,7 @@ class ContactsTest extends TestCase
$response->assertRedirect('/admin/contacts/' . $contact->id . '/edit'); $response->assertRedirect('/admin/contacts/' . $contact->id . '/edit');
} }
/** @test */ #[Test]
public function gettingRemoteAvatarFailsGracefullyWithRemoteError(): void public function gettingRemoteAvatarFailsGracefullyWithRemoteError(): void
{ {
$html = <<<'HTML' $html = <<<'HTML'
@ -201,7 +202,7 @@ class ContactsTest extends TestCase
$response->assertRedirect('/admin/contacts/' . $contact->id . '/edit'); $response->assertRedirect('/admin/contacts/' . $contact->id . '/edit');
} }
/** @test */ #[Test]
public function gettingRemoteAvatarFailsGracefullyForContactWithNoHompage(): void public function gettingRemoteAvatarFailsGracefullyForContactWithNoHompage(): void
{ {
$contact = Contact::create([ $contact = Contact::create([

View file

@ -9,13 +9,14 @@ use App\Models\Like;
use App\Models\User; use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Queue; use Illuminate\Support\Facades\Queue;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class LikesTest extends TestCase class LikesTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
/** @test */ #[Test]
public function likesPageLoads(): void public function likesPageLoads(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -25,7 +26,7 @@ class LikesTest extends TestCase
$response->assertSeeText('Likes'); $response->assertSeeText('Likes');
} }
/** @test */ #[Test]
public function likeCreateFormLoads(): void public function likeCreateFormLoads(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -35,7 +36,7 @@ class LikesTest extends TestCase
$response->assertSeeText('New Like'); $response->assertSeeText('New Like');
} }
/** @test */ #[Test]
public function adminCanCreateLike(): void public function adminCanCreateLike(): void
{ {
Queue::fake(); Queue::fake();
@ -51,7 +52,7 @@ class LikesTest extends TestCase
Queue::assertPushed(ProcessLike::class); Queue::assertPushed(ProcessLike::class);
} }
/** @test */ #[Test]
public function likeEditFormLoads(): void public function likeEditFormLoads(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -62,7 +63,7 @@ class LikesTest extends TestCase
$response->assertSee('Edit Like'); $response->assertSee('Edit Like');
} }
/** @test */ #[Test]
public function adminCanEditLike(): void public function adminCanEditLike(): void
{ {
Queue::fake(); Queue::fake();
@ -80,7 +81,7 @@ class LikesTest extends TestCase
Queue::assertPushed(ProcessLike::class); Queue::assertPushed(ProcessLike::class);
} }
/** @test */ #[Test]
public function adminCanDeleteLike(): void public function adminCanDeleteLike(): void
{ {
$like = Like::factory()->create(); $like = Like::factory()->create();

View file

@ -9,13 +9,14 @@ use App\Models\Note;
use App\Models\User; use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Queue; use Illuminate\Support\Facades\Queue;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class NotesTest extends TestCase class NotesTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
/** @test */ #[Test]
public function notesPageLoads(): void public function notesPageLoads(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -24,7 +25,7 @@ class NotesTest extends TestCase
$response->assertViewIs('admin.notes.index'); $response->assertViewIs('admin.notes.index');
} }
/** @test */ #[Test]
public function noteCreatePageLoads(): void public function noteCreatePageLoads(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -33,7 +34,7 @@ class NotesTest extends TestCase
$response->assertViewIs('admin.notes.create'); $response->assertViewIs('admin.notes.create');
} }
/** @test */ #[Test]
public function adminCanCreateNewNote(): void public function adminCanCreateNewNote(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -47,7 +48,7 @@ class NotesTest extends TestCase
]); ]);
} }
/** @test */ #[Test]
public function noteEditFormLoads(): void public function noteEditFormLoads(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -57,7 +58,7 @@ class NotesTest extends TestCase
$response->assertViewIs('admin.notes.edit'); $response->assertViewIs('admin.notes.edit');
} }
/** @test */ #[Test]
public function adminCanEditNote(): void public function adminCanEditNote(): void
{ {
Queue::fake(); Queue::fake();
@ -76,7 +77,7 @@ class NotesTest extends TestCase
Queue::assertPushed(SendWebMentions::class); Queue::assertPushed(SendWebMentions::class);
} }
/** @test */ #[Test]
public function adminCanDeleteNote(): void public function adminCanDeleteNote(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();

View file

@ -7,13 +7,14 @@ namespace Tests\Feature\Admin;
use App\Models\Place; use App\Models\Place;
use App\Models\User; use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class PlacesTest extends TestCase class PlacesTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
/** @test */ #[Test]
public function placesPageLoads(): void public function placesPageLoads(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -22,7 +23,7 @@ class PlacesTest extends TestCase
$response->assertViewIs('admin.places.index'); $response->assertViewIs('admin.places.index');
} }
/** @test */ #[Test]
public function createPlacePageLoads(): void public function createPlacePageLoads(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -31,7 +32,7 @@ class PlacesTest extends TestCase
$response->assertViewIs('admin.places.create'); $response->assertViewIs('admin.places.create');
} }
/** @test */ #[Test]
public function adminCanCreateNewPlace(): void public function adminCanCreateNewPlace(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -48,7 +49,7 @@ class PlacesTest extends TestCase
]); ]);
} }
/** @test */ #[Test]
public function editPlacePageLoads(): void public function editPlacePageLoads(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();
@ -58,7 +59,7 @@ class PlacesTest extends TestCase
$response->assertViewIs('admin.places.edit'); $response->assertViewIs('admin.places.edit');
} }
/** @test */ #[Test]
public function adminCanUpdatePlace(): void public function adminCanUpdatePlace(): void
{ {
$user = User::factory()->make(); $user = User::factory()->make();

View file

@ -7,20 +7,21 @@ namespace Tests\Feature;
use App\Models\Article; use App\Models\Article;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Jonnybarnes\IndieWeb\Numbers; use Jonnybarnes\IndieWeb\Numbers;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class ArticlesTest extends TestCase class ArticlesTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
/** @test */ #[Test]
public function articlesPageLoads(): void public function articlesPageLoads(): void
{ {
$response = $this->get('/blog'); $response = $this->get('/blog');
$response->assertViewIs('articles.index'); $response->assertViewIs('articles.index');
} }
/** @test */ #[Test]
public function singleArticlePageLoads() public function singleArticlePageLoads()
{ {
$article = Article::factory()->create(); $article = Article::factory()->create();
@ -28,7 +29,7 @@ class ArticlesTest extends TestCase
$response->assertViewIs('articles.show'); $response->assertViewIs('articles.show');
} }
/** @test */ #[Test]
public function wrongDateInUrlRedirectsToCorrectDate() public function wrongDateInUrlRedirectsToCorrectDate()
{ {
$article = Article::factory()->create(); $article = Article::factory()->create();
@ -36,7 +37,7 @@ class ArticlesTest extends TestCase
$response->assertRedirect('/blog/' . date('Y') . '/' . date('m') . '/' . $article->titleurl); $response->assertRedirect('/blog/' . date('Y') . '/' . date('m') . '/' . $article->titleurl);
} }
/** @test */ #[Test]
public function oldUrlsWithIdAreRedirected() public function oldUrlsWithIdAreRedirected()
{ {
$article = Article::factory()->create(); $article = Article::factory()->create();
@ -45,21 +46,21 @@ class ArticlesTest extends TestCase
$response->assertRedirect($article->link); $response->assertRedirect($article->link);
} }
/** @test */ #[Test]
public function unknownSlugGetsNotFoundResponse() public function unknownSlugGetsNotFoundResponse()
{ {
$response = $this->get('/blog/' . date('Y') . '/' . date('m') . '/unknown-slug'); $response = $this->get('/blog/' . date('Y') . '/' . date('m') . '/unknown-slug');
$response->assertNotFound(); $response->assertNotFound();
} }
/** @test */ #[Test]
public function unknownArticleIdGetsNotFoundResponse() public function unknownArticleIdGetsNotFoundResponse()
{ {
$response = $this->get('/blog/s/22'); $response = $this->get('/blog/s/22');
$response->assertNotFound(); $response->assertNotFound();
} }
/** @test */ #[Test]
public function someUrlsDoNotParseCorrectly(): void public function someUrlsDoNotParseCorrectly(): void
{ {
$response = $this->get('/blog/feed.js'); $response = $this->get('/blog/feed.js');

View file

@ -8,6 +8,7 @@ use App\Jobs\ProcessBookmark;
use App\Models\Bookmark; use App\Models\Bookmark;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Queue; use Illuminate\Support\Facades\Queue;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
use Tests\TestToken; use Tests\TestToken;
@ -15,14 +16,14 @@ class BookmarksTest extends TestCase
{ {
use RefreshDatabase, TestToken; use RefreshDatabase, TestToken;
/** @test */ #[Test]
public function bookmarksPageLoadsWithoutError(): void public function bookmarksPageLoadsWithoutError(): void
{ {
$response = $this->get('/bookmarks'); $response = $this->get('/bookmarks');
$response->assertViewIs('bookmarks.index'); $response->assertViewIs('bookmarks.index');
} }
/** @test */ #[Test]
public function singleBookmarkPageLoadsWithoutError(): void public function singleBookmarkPageLoadsWithoutError(): void
{ {
$bookmark = Bookmark::factory()->create(); $bookmark = Bookmark::factory()->create();
@ -30,7 +31,7 @@ class BookmarksTest extends TestCase
$response->assertViewIs('bookmarks.show'); $response->assertViewIs('bookmarks.show');
} }
/** @test */ #[Test]
public function whenBookmarkIsAddedUsingHttpSyntaxCheckJobToTakeScreenshotIsInvoked(): void public function whenBookmarkIsAddedUsingHttpSyntaxCheckJobToTakeScreenshotIsInvoked(): void
{ {
Queue::fake(); Queue::fake();
@ -48,7 +49,7 @@ class BookmarksTest extends TestCase
$this->assertDatabaseHas('bookmarks', ['url' => 'https://example.org/blog-post']); $this->assertDatabaseHas('bookmarks', ['url' => 'https://example.org/blog-post']);
} }
/** @test */ #[Test]
public function whenBookmarkIsAddedUsingJsonSyntaxCheckJobToTakeScreenshotIsInvoked(): void public function whenBookmarkIsAddedUsingJsonSyntaxCheckJobToTakeScreenshotIsInvoked(): void
{ {
Queue::fake(); Queue::fake();
@ -68,7 +69,7 @@ class BookmarksTest extends TestCase
$this->assertDatabaseHas('bookmarks', ['url' => 'https://example.org/blog-post']); $this->assertDatabaseHas('bookmarks', ['url' => 'https://example.org/blog-post']);
} }
/** @test */ #[Test]
public function whenTheBookmarkIsCreatedCheckNecessaryTagsAreAlsoCreated(): void public function whenTheBookmarkIsCreatedCheckNecessaryTagsAreAlsoCreated(): void
{ {
Queue::fake(); Queue::fake();

View file

@ -6,6 +6,7 @@ namespace Tests\Feature;
use App\Models\Contact; use App\Models\Contact;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class ContactsTest extends TestCase class ContactsTest extends TestCase
@ -14,9 +15,8 @@ class ContactsTest extends TestCase
/** /**
* Check the `/contacts` page gives a good response. * Check the `/contacts` page gives a good response.
*
* @test
*/ */
#[Test]
public function contactsPageLoadsWithoutError(): void public function contactsPageLoadsWithoutError(): void
{ {
$response = $this->get('/contacts'); $response = $this->get('/contacts');
@ -25,9 +25,8 @@ class ContactsTest extends TestCase
/** /**
* Test an individual contact page with default profile image. * Test an individual contact page with default profile image.
*
* @test
*/ */
#[Test]
public function contactPageShouldFallbackToDefaultProfilePic(): void public function contactPageShouldFallbackToDefaultProfilePic(): void
{ {
Contact::factory()->create([ Contact::factory()->create([
@ -39,9 +38,8 @@ class ContactsTest extends TestCase
/** /**
* Test an individual contact page with a specific profile image. * Test an individual contact page with a specific profile image.
*
* @test
*/ */
#[Test]
public function contactPageShouldUseSpecificProfilePicIfPresent(): void public function contactPageShouldUseSpecificProfilePicIfPresent(): void
{ {
Contact::factory()->create([ Contact::factory()->create([
@ -52,7 +50,7 @@ class ContactsTest extends TestCase
$response->assertViewHas('image', '/assets/profile-images/aaronparecki.com/image'); $response->assertViewHas('image', '/assets/profile-images/aaronparecki.com/image');
} }
/** @test */ #[Test]
public function unknownContactReturnsNotFoundResponse(): void public function unknownContactReturnsNotFoundResponse(): void
{ {
$response = $this->get('/contacts/unknown'); $response = $this->get('/contacts/unknown');

View file

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Tests\Feature; namespace Tests\Feature;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
use Tests\TestToken; use Tests\TestToken;
@ -11,7 +12,7 @@ class CorsHeadersTest extends TestCase
{ {
use TestToken; use TestToken;
/** @test */ #[Test]
public function checkCorsHeadersOnMediaEndpoint(): void public function checkCorsHeadersOnMediaEndpoint(): void
{ {
$response = $this->call( $response = $this->call(
@ -25,7 +26,7 @@ class CorsHeadersTest extends TestCase
$response->assertHeader('Access-Control-Allow-Origin', '*'); $response->assertHeader('Access-Control-Allow-Origin', '*');
} }
/** @test */ #[Test]
public function checkForNoCorsHeaderOnNonMediaEndpointLinks(): void public function checkForNoCorsHeaderOnNonMediaEndpointLinks(): void
{ {
$response = $this->get('/blog'); $response = $this->get('/blog');

View file

@ -8,6 +8,7 @@ use App\Models\Article;
use App\Models\Note; use App\Models\Note;
use App\Models\Place; use App\Models\Place;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class FeedsTest extends TestCase class FeedsTest extends TestCase
@ -16,9 +17,8 @@ class FeedsTest extends TestCase
/** /**
* Test the blog RSS feed. * Test the blog RSS feed.
*
* @test
*/ */
#[Test]
public function blogRssFeedIsPresent(): void public function blogRssFeedIsPresent(): void
{ {
Article::factory()->count(3)->create(); Article::factory()->count(3)->create();
@ -29,9 +29,8 @@ class FeedsTest extends TestCase
/** /**
* Test the notes RSS feed. * Test the notes RSS feed.
*
* @test
*/ */
#[Test]
public function notesRssFeedIsPresent(): void public function notesRssFeedIsPresent(): void
{ {
Note::factory()->count(3)->create(); Note::factory()->count(3)->create();
@ -42,9 +41,8 @@ class FeedsTest extends TestCase
/** /**
* Test the blog RSS feed. * Test the blog RSS feed.
*
* @test
*/ */
#[Test]
public function blogAtomFeedIsPresent(): void public function blogAtomFeedIsPresent(): void
{ {
Article::factory()->count(3)->create(); Article::factory()->count(3)->create();
@ -53,7 +51,7 @@ class FeedsTest extends TestCase
$response->assertOk(); $response->assertOk();
} }
/** @test */ #[Test]
public function blogJf2FeedIsPresent(): void public function blogJf2FeedIsPresent(): void
{ {
Article::factory()->count(3)->create(); Article::factory()->count(3)->create();
@ -77,9 +75,8 @@ class FeedsTest extends TestCase
/** /**
* Test the notes RSS feed. * Test the notes RSS feed.
*
* @test
*/ */
#[Test]
public function notesAtomFeedIsPresent(): void public function notesAtomFeedIsPresent(): void
{ {
Note::factory()->count(3)->create(); Note::factory()->count(3)->create();
@ -90,9 +87,8 @@ class FeedsTest extends TestCase
/** /**
* Test the blog JSON feed. * Test the blog JSON feed.
*
* @test
*/ */
#[Test]
public function blogJsonFeedIsPresent(): void public function blogJsonFeedIsPresent(): void
{ {
Article::factory()->count(3)->create(); Article::factory()->count(3)->create();
@ -103,9 +99,8 @@ class FeedsTest extends TestCase
/** /**
* Test the notes JSON feed. * Test the notes JSON feed.
*
* @test
*/ */
#[Test]
public function notesJsonFeedIsPresent(): void public function notesJsonFeedIsPresent(): void
{ {
Note::factory()->count(3)->create(); Note::factory()->count(3)->create();
@ -114,7 +109,7 @@ class FeedsTest extends TestCase
$response->assertOk(); $response->assertOk();
} }
/** @test */ #[Test]
public function notesJf2FeedIsPresent(): void public function notesJf2FeedIsPresent(): void
{ {
Note::factory()->count(3)->create(); Note::factory()->count(3)->create();
@ -139,9 +134,8 @@ class FeedsTest extends TestCase
/** /**
* Each JSON feed item must have one of `content_text` or `content_html`, * Each JSON feed item must have one of `content_text` or `content_html`,
* and whichever one they have cant be `null`. * and whichever one they have cant be `null`.
*
* @test
*/ */
#[Test]
public function jsonFeedsHaveRequiredAttributes(): void public function jsonFeedsHaveRequiredAttributes(): void
{ {
Note::factory()->count(3)->create(); Note::factory()->count(3)->create();
@ -161,7 +155,7 @@ class FeedsTest extends TestCase
} }
} }
/** @test */ #[Test]
public function jsonNoteFeedLoadsPlaceDataWithoutLazyLoading(): void public function jsonNoteFeedLoadsPlaceDataWithoutLazyLoading(): void
{ {
$place = Place::factory()->create(); $place = Place::factory()->create();

View file

@ -7,13 +7,14 @@ use App\Models\Bookmark;
use App\Models\Like; use App\Models\Like;
use App\Models\Note; use App\Models\Note;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class FrontPageTest extends TestCase class FrontPageTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
/** @test */ #[Test]
public function frontPageLoadsAllContent(): void public function frontPageLoadsAllContent(): void
{ {
Note::factory()->create(['note' => 'Note 1']); Note::factory()->create(['note' => 'Note 1']);

View file

@ -3,15 +3,15 @@
namespace Tests\Feature; namespace Tests\Feature;
use App\Models\User; use App\Models\User;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class HorizonTest extends TestCase class HorizonTest extends TestCase
{ {
/** /**
* Horizon has its own test suite, here we just test it has been installed successfully. * Horizon has its own test suite, here we just test it has been installed successfully.
*
* @test
*/ */
#[Test]
public function horizonIsInstalled(): void public function horizonIsInstalled(): void
{ {
$user = User::factory()->create([ $user = User::factory()->create([

View file

@ -31,8 +31,8 @@ class IndieAuthTest extends TestCase
'authorization_endpoint' => route('indieauth.start'), 'authorization_endpoint' => route('indieauth.start'),
'token_endpoint' => route('indieauth.token'), 'token_endpoint' => route('indieauth.token'),
'code_challenge_methods_supported' => ['S256'], 'code_challenge_methods_supported' => ['S256'],
//'introspection_endpoint' => 'introspection_endpoint', // 'introspection_endpoint' => 'introspection_endpoint',
//'introspection_endpoint_auth_methods_supported' => ['none'], // 'introspection_endpoint_auth_methods_supported' => ['none'],
]); ]);
} }

View file

@ -14,6 +14,7 @@ use GuzzleHttp\Psr7\Response;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Queue; use Illuminate\Support\Facades\Queue;
use Jonnybarnes\WebmentionsParser\Authorship; use Jonnybarnes\WebmentionsParser\Authorship;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
use Tests\TestToken; use Tests\TestToken;
@ -22,14 +23,14 @@ class LikesTest extends TestCase
use RefreshDatabase; use RefreshDatabase;
use TestToken; use TestToken;
/** @test */ #[Test]
public function likesPageHasCorrectView(): void public function likesPageHasCorrectView(): void
{ {
$response = $this->get('/likes'); $response = $this->get('/likes');
$response->assertViewIs('likes.index'); $response->assertViewIs('likes.index');
} }
/** @test */ #[Test]
public function singleLikePageHasCorrectView(): void public function singleLikePageHasCorrectView(): void
{ {
$like = Like::factory()->create(); $like = Like::factory()->create();
@ -37,7 +38,7 @@ class LikesTest extends TestCase
$response->assertViewIs('likes.show'); $response->assertViewIs('likes.show');
} }
/** @test */ #[Test]
public function checkLikeCreatedFromMicropubApiRequests(): void public function checkLikeCreatedFromMicropubApiRequests(): void
{ {
Queue::fake(); Queue::fake();
@ -57,7 +58,7 @@ class LikesTest extends TestCase
$this->assertDatabaseHas('likes', ['url' => 'https://example.org/blog-post']); $this->assertDatabaseHas('likes', ['url' => 'https://example.org/blog-post']);
} }
/** @test */ #[Test]
public function checkLikeCreatedFromMicropubWebRequests(): void public function checkLikeCreatedFromMicropubWebRequests(): void
{ {
Queue::fake(); Queue::fake();
@ -75,7 +76,7 @@ class LikesTest extends TestCase
$this->assertDatabaseHas('likes', ['url' => 'https://example.org/blog-post']); $this->assertDatabaseHas('likes', ['url' => 'https://example.org/blog-post']);
} }
/** @test */ #[Test]
public function likeWithSimpleAuthor(): void public function likeWithSimpleAuthor(): void
{ {
$like = new Like; $like = new Like;
@ -114,7 +115,7 @@ class LikesTest extends TestCase
$this->assertEquals('Fred Bloggs', Like::find($id)->author_name); $this->assertEquals('Fred Bloggs', Like::find($id)->author_name);
} }
/** @test */ #[Test]
public function likeWithHCard(): void public function likeWithHCard(): void
{ {
$like = new Like; $like = new Like;
@ -157,7 +158,7 @@ class LikesTest extends TestCase
$this->assertEquals('Fred Bloggs', Like::find($id)->author_name); $this->assertEquals('Fred Bloggs', Like::find($id)->author_name);
} }
/** @test */ #[Test]
public function likeWithoutMicroformats(): void public function likeWithoutMicroformats(): void
{ {
$like = new Like; $like = new Like;
@ -193,7 +194,7 @@ class LikesTest extends TestCase
$this->assertNull(Like::find($id)->author_name); $this->assertNull(Like::find($id)->author_name);
} }
/** @test */ #[Test]
public function likeThatIsATweet(): void public function likeThatIsATweet(): void
{ {
$like = new Like; $like = new Like;
@ -219,10 +220,9 @@ class LikesTest extends TestCase
'author_url' => 'https://twitter.com/jonnybarnes', 'author_url' => 'https://twitter.com/jonnybarnes',
'html' => '<div>HTML of the tweet embed</div>', 'html' => '<div>HTML of the tweet embed</div>',
]; ];
$codebirdMock = $this->getMockBuilder(Codebird::class) $codebirdMock = $this->createPartialMock(Codebird::class, ['__call']);
->addMethods(['statuses_oembed']) $codebirdMock->method('__call')
->getMock(); ->with('statuses_oembed', $this->anything())
$codebirdMock->method('statuses_oembed')
->willReturn($info); ->willReturn($info);
$this->app->instance(Codebird::class, $codebirdMock); $this->app->instance(Codebird::class, $codebirdMock);
@ -233,7 +233,7 @@ class LikesTest extends TestCase
$this->assertEquals('Jonny Barnes', Like::find($id)->author_name); $this->assertEquals('Jonny Barnes', Like::find($id)->author_name);
} }
/** @test */ #[Test]
public function noErrorForFailureToPosseWithBridgy(): void public function noErrorForFailureToPosseWithBridgy(): void
{ {
$like = new Like; $like = new Like;
@ -257,10 +257,9 @@ class LikesTest extends TestCase
'author_url' => 'https://twitter.com/jonnybarnes', 'author_url' => 'https://twitter.com/jonnybarnes',
'html' => '<div>HTML of the tweet embed</div>', 'html' => '<div>HTML of the tweet embed</div>',
]; ];
$codebirdMock = $this->getMockBuilder(Codebird::class) $codebirdMock = $this->createPartialMock(Codebird::class, ['__call']);
->addMethods(['statuses_oembed']) $codebirdMock->method('__call')
->getMock(); ->with('statuses_oembed', $this->anything())
$codebirdMock->method('statuses_oembed')
->willReturn($info); ->willReturn($info);
$this->app->instance(Codebird::class, $codebirdMock); $this->app->instance(Codebird::class, $codebirdMock);
@ -271,7 +270,7 @@ class LikesTest extends TestCase
$this->assertEquals('Jonny Barnes', Like::find($id)->author_name); $this->assertEquals('Jonny Barnes', Like::find($id)->author_name);
} }
/** @test */ #[Test]
public function unknownLikeGivesNotFoundResponse(): void public function unknownLikeGivesNotFoundResponse(): void
{ {
$response = $this->get('/likes/202'); $response = $this->get('/likes/202');

View file

@ -15,6 +15,7 @@ use Carbon\Carbon;
use Faker\Factory; use Faker\Factory;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Queue; use Illuminate\Support\Facades\Queue;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
use Tests\TestToken; use Tests\TestToken;
@ -23,7 +24,7 @@ class MicropubControllerTest extends TestCase
use RefreshDatabase; use RefreshDatabase;
use TestToken; use TestToken;
/** @test */ #[Test]
public function micropubGetRequestWithoutTokenReturnsErrorResponse(): void public function micropubGetRequestWithoutTokenReturnsErrorResponse(): void
{ {
$response = $this->get('/api/post'); $response = $this->get('/api/post');
@ -31,7 +32,7 @@ class MicropubControllerTest extends TestCase
$response->assertJsonFragment(['error_description' => 'No access token was provided in the request']); $response->assertJsonFragment(['error_description' => 'No access token was provided in the request']);
} }
/** @test */ #[Test]
public function micropubGetRequestWithoutValidTokenReturnsErrorResponse(): void public function micropubGetRequestWithoutValidTokenReturnsErrorResponse(): void
{ {
$response = $this->get('/api/post', ['HTTP_Authorization' => 'Bearer abc123']); $response = $this->get('/api/post', ['HTTP_Authorization' => 'Bearer abc123']);
@ -42,9 +43,8 @@ class MicropubControllerTest extends TestCase
/** /**
* Test a GET request for the micropub endpoint with a valid token gives a * Test a GET request for the micropub endpoint with a valid token gives a
* 200 response. Check token information is also returned in the response. * 200 response. Check token information is also returned in the response.
*
* @test
*/ */
#[Test]
public function micropubGetRequestWithValidTokenReturnsOkResponse(): void public function micropubGetRequestWithValidTokenReturnsOkResponse(): void
{ {
$response = $this->get('/api/post', ['HTTP_Authorization' => 'Bearer ' . $this->getToken()]); $response = $this->get('/api/post', ['HTTP_Authorization' => 'Bearer ' . $this->getToken()]);
@ -52,14 +52,14 @@ class MicropubControllerTest extends TestCase
$response->assertJsonFragment(['response' => 'token']); $response->assertJsonFragment(['response' => 'token']);
} }
/** @test */ #[Test]
public function micropubClientsCanRequestSyndicationTargetsCanBeEmpty(): void public function micropubClientsCanRequestSyndicationTargetsCanBeEmpty(): void
{ {
$response = $this->get('/api/post?q=syndicate-to', ['HTTP_Authorization' => 'Bearer ' . $this->getToken()]); $response = $this->get('/api/post?q=syndicate-to', ['HTTP_Authorization' => 'Bearer ' . $this->getToken()]);
$response->assertJsonFragment(['syndicate-to' => []]); $response->assertJsonFragment(['syndicate-to' => []]);
} }
/** @test */ #[Test]
public function micropubClientsCanRequestSyndicationTargetsPopulatesFromModel(): void public function micropubClientsCanRequestSyndicationTargetsPopulatesFromModel(): void
{ {
$syndicationTarget = SyndicationTarget::factory()->create(); $syndicationTarget = SyndicationTarget::factory()->create();
@ -67,7 +67,7 @@ class MicropubControllerTest extends TestCase
$response->assertJsonFragment(['uid' => $syndicationTarget->uid]); $response->assertJsonFragment(['uid' => $syndicationTarget->uid]);
} }
/** @test */ #[Test]
public function micropubClientsCanRequestKnownNearbyPlaces(): void public function micropubClientsCanRequestKnownNearbyPlaces(): void
{ {
Place::factory()->create([ Place::factory()->create([
@ -80,8 +80,6 @@ class MicropubControllerTest extends TestCase
} }
/** /**
* @test
*
* @todo Add uncertainty parameter * @todo Add uncertainty parameter
* *
public function micropubClientsCanRequestKnownNearbyPlacesWithUncertaintyParameter(): void public function micropubClientsCanRequestKnownNearbyPlacesWithUncertaintyParameter(): void
@ -89,22 +87,21 @@ class MicropubControllerTest extends TestCase
$response = $this->get('/api/post?q=geo:53.5,-2.38', ['HTTP_Authorization' => 'Bearer ' . $this->getToken()]); $response = $this->get('/api/post?q=geo:53.5,-2.38', ['HTTP_Authorization' => 'Bearer ' . $this->getToken()]);
$response->assertJson(['places' => [['slug' => 'the-bridgewater-pub']]]); $response->assertJson(['places' => [['slug' => 'the-bridgewater-pub']]]);
}*/ }*/
#[Test]
/** @test */
public function returnEmptyResultWhenMicropubClientRequestsKnownNearbyPlaces(): void public function returnEmptyResultWhenMicropubClientRequestsKnownNearbyPlaces(): void
{ {
$response = $this->get('/api/post?q=geo:1.23,4.56', ['HTTP_Authorization' => 'Bearer ' . $this->getToken()]); $response = $this->get('/api/post?q=geo:1.23,4.56', ['HTTP_Authorization' => 'Bearer ' . $this->getToken()]);
$response->assertJson(['places' => []]); $response->assertJson(['places' => []]);
} }
/** @test */ #[Test]
public function micropubClientCanRequestEndpointConfig(): void public function micropubClientCanRequestEndpointConfig(): void
{ {
$response = $this->get('/api/post?q=config', ['HTTP_Authorization' => 'Bearer ' . $this->getToken()]); $response = $this->get('/api/post?q=config', ['HTTP_Authorization' => 'Bearer ' . $this->getToken()]);
$response->assertJsonFragment(['media-endpoint' => route('media-endpoint')]); $response->assertJsonFragment(['media-endpoint' => route('media-endpoint')]);
} }
/** @test */ #[Test]
public function micropubClientCanCreateNewNote(): void public function micropubClientCanCreateNewNote(): void
{ {
$faker = Factory::create(); $faker = Factory::create();
@ -123,7 +120,7 @@ class MicropubControllerTest extends TestCase
$this->assertDatabaseHas('notes', ['note' => $note]); $this->assertDatabaseHas('notes', ['note' => $note]);
} }
/** @test */ #[Test]
public function micropubClientCanRequestTheNewNoteIsSyndicatedToMastodonAndBluesky(): void public function micropubClientCanRequestTheNewNoteIsSyndicatedToMastodonAndBluesky(): void
{ {
Queue::fake(); Queue::fake();
@ -157,7 +154,7 @@ class MicropubControllerTest extends TestCase
Queue::assertPushed(SyndicateNoteToBluesky::class); Queue::assertPushed(SyndicateNoteToBluesky::class);
} }
/** @test */ #[Test]
public function micropubClientsCanCreateNewPlaces(): void public function micropubClientsCanCreateNewPlaces(): void
{ {
$response = $this->post( $response = $this->post(
@ -173,7 +170,7 @@ class MicropubControllerTest extends TestCase
$this->assertDatabaseHas('places', ['slug' => 'the-barton-arms']); $this->assertDatabaseHas('places', ['slug' => 'the-barton-arms']);
} }
/** @test */ #[Test]
public function micropubClientsCanCreateNewPlacesWithOldLocationSyntax(): void public function micropubClientsCanCreateNewPlacesWithOldLocationSyntax(): void
{ {
$response = $this->post( $response = $this->post(
@ -190,7 +187,7 @@ class MicropubControllerTest extends TestCase
$this->assertDatabaseHas('places', ['slug' => 'the-barton-arms']); $this->assertDatabaseHas('places', ['slug' => 'the-barton-arms']);
} }
/** @test */ #[Test]
public function micropubClientWebRequestWithInvalidTokenReturnsErrorResponse(): void public function micropubClientWebRequestWithInvalidTokenReturnsErrorResponse(): void
{ {
$response = $this->post( $response = $this->post(
@ -205,7 +202,7 @@ class MicropubControllerTest extends TestCase
$response->assertJson(['error' => 'invalid_token']); $response->assertJson(['error' => 'invalid_token']);
} }
/** @test */ #[Test]
public function micropubClientWebRequestWithTokenWithoutAnyScopesReturnsErrorResponse(): void public function micropubClientWebRequestWithTokenWithoutAnyScopesReturnsErrorResponse(): void
{ {
$response = $this->post( $response = $this->post(
@ -220,7 +217,7 @@ class MicropubControllerTest extends TestCase
$response->assertJson(['error_description' => 'The provided token has no scopes']); $response->assertJson(['error_description' => 'The provided token has no scopes']);
} }
/** @test */ #[Test]
public function micropubClientWebRequestWithTokenWithoutCreateScopesReturnsErrorResponse(): void public function micropubClientWebRequestWithTokenWithoutCreateScopesReturnsErrorResponse(): void
{ {
$response = $this->post( $response = $this->post(
@ -238,9 +235,8 @@ class MicropubControllerTest extends TestCase
/** /**
* Test a valid micropub requests using JSON syntax creates a new note. * Test a valid micropub requests using JSON syntax creates a new note.
*
* @test
*/ */
#[Test]
public function micropubClientApiRequestCreatesNewNote(): void public function micropubClientApiRequestCreatesNewNote(): void
{ {
Queue::fake(); Queue::fake();
@ -286,9 +282,8 @@ class MicropubControllerTest extends TestCase
/** /**
* Test a valid micropub requests using JSON syntax creates a new note with * Test a valid micropub requests using JSON syntax creates a new note with
* existing self-created place. * existing self-created place.
*
* @test
*/ */
#[Test]
public function micropubClientApiRequestCreatesNewNoteWithExistingPlaceInLocationData(): void public function micropubClientApiRequestCreatesNewNoteWithExistingPlaceInLocationData(): void
{ {
$place = new Place; $place = new Place;
@ -317,9 +312,8 @@ class MicropubControllerTest extends TestCase
/** /**
* Test a valid micropub requests using JSON syntax creates a new note with * Test a valid micropub requests using JSON syntax creates a new note with
* a new place defined in the location block. * a new place defined in the location block.
*
* @test
*/ */
#[Test]
public function micropubClientApiRequestCreatesNewNoteWithNewPlaceInLocationData(): void public function micropubClientApiRequestCreatesNewNoteWithNewPlaceInLocationData(): void
{ {
$faker = Factory::create(); $faker = Factory::create();
@ -353,9 +347,8 @@ class MicropubControllerTest extends TestCase
/** /**
* Test a valid micropub requests using JSON syntax creates a new note without * Test a valid micropub requests using JSON syntax creates a new note without
* a new place defined in the location block if there is missing data. * a new place defined in the location block if there is missing data.
*
* @test
*/ */
#[Test]
public function micropubClientApiRequestCreatesNewNoteWithoutNewPlaceInLocationData(): void public function micropubClientApiRequestCreatesNewNoteWithoutNewPlaceInLocationData(): void
{ {
$faker = Factory::create(); $faker = Factory::create();
@ -387,9 +380,8 @@ class MicropubControllerTest extends TestCase
/** /**
* Test a micropub requests using JSON syntax without a token returns an * Test a micropub requests using JSON syntax without a token returns an
* error. Also check the message. * error. Also check the message.
*
* @test
*/ */
#[Test]
public function micropubClientApiRequestWithoutTokenReturnsError(): void public function micropubClientApiRequestWithoutTokenReturnsError(): void
{ {
$faker = Factory::create(); $faker = Factory::create();
@ -414,9 +406,8 @@ class MicropubControllerTest extends TestCase
/** /**
* Test a micropub requests using JSON syntax without a valid token returns * Test a micropub requests using JSON syntax without a valid token returns
* an error. Also check the message. * an error. Also check the message.
*
* @test
*/ */
#[Test]
public function micropubClientApiRequestWithTokenWithInsufficientPermissionReturnsError(): void public function micropubClientApiRequestWithTokenWithInsufficientPermissionReturnsError(): void
{ {
$faker = Factory::create(); $faker = Factory::create();
@ -439,7 +430,7 @@ class MicropubControllerTest extends TestCase
->assertStatus(401); ->assertStatus(401);
} }
/** @test */ #[Test]
public function micropubClientApiRequestForUnsupportedPostTypeReturnsError(): void public function micropubClientApiRequestForUnsupportedPostTypeReturnsError(): void
{ {
$response = $this->postJson( $response = $this->postJson(
@ -460,7 +451,7 @@ class MicropubControllerTest extends TestCase
->assertStatus(500); ->assertStatus(500);
} }
/** @test */ #[Test]
public function micropubClientApiRequestCreatesNewPlace(): void public function micropubClientApiRequestCreatesNewPlace(): void
{ {
$faker = Factory::create(); $faker = Factory::create();
@ -480,7 +471,7 @@ class MicropubControllerTest extends TestCase
->assertStatus(201); ->assertStatus(201);
} }
/** @test */ #[Test]
public function micropubClientApiRequestCreatesNewPlaceWithUncertaintyParameter(): void public function micropubClientApiRequestCreatesNewPlaceWithUncertaintyParameter(): void
{ {
$faker = Factory::create(); $faker = Factory::create();
@ -500,7 +491,7 @@ class MicropubControllerTest extends TestCase
->assertStatus(201); ->assertStatus(201);
} }
/** @test */ #[Test]
public function micropubClientApiRequestUpdatesExistingNote(): void public function micropubClientApiRequestUpdatesExistingNote(): void
{ {
$note = Note::factory()->create(); $note = Note::factory()->create();
@ -520,7 +511,7 @@ class MicropubControllerTest extends TestCase
->assertStatus(200); ->assertStatus(200);
} }
/** @test */ #[Test]
public function micropubClientApiRequestUpdatesNoteSyndicationLinks(): void public function micropubClientApiRequestUpdatesNoteSyndicationLinks(): void
{ {
$note = Note::factory()->create(); $note = Note::factory()->create();
@ -547,7 +538,7 @@ class MicropubControllerTest extends TestCase
]); ]);
} }
/** @test */ #[Test]
public function micropubClientApiRequestAddsImageToNote(): void public function micropubClientApiRequestAddsImageToNote(): void
{ {
$note = Note::factory()->create(); $note = Note::factory()->create();
@ -570,7 +561,7 @@ class MicropubControllerTest extends TestCase
]); ]);
} }
/** @test */ #[Test]
public function micropubClientApiRequestReturnsErrorTryingToUpdateNonNoteModel(): void public function micropubClientApiRequestReturnsErrorTryingToUpdateNonNoteModel(): void
{ {
$response = $this->postJson( $response = $this->postJson(
@ -589,7 +580,7 @@ class MicropubControllerTest extends TestCase
->assertStatus(500); ->assertStatus(500);
} }
/** @test */ #[Test]
public function micropubClientApiRequestReturnsErrorTryingToUpdateNonExistingNote(): void public function micropubClientApiRequestReturnsErrorTryingToUpdateNonExistingNote(): void
{ {
$response = $this->postJson( $response = $this->postJson(
@ -608,7 +599,7 @@ class MicropubControllerTest extends TestCase
->assertStatus(404); ->assertStatus(404);
} }
/** @test */ #[Test]
public function micropubClientApiRequestReturnsErrorWhenTryingToUpdateUnsupportedProperty(): void public function micropubClientApiRequestReturnsErrorWhenTryingToUpdateUnsupportedProperty(): void
{ {
$note = Note::factory()->create(); $note = Note::factory()->create();
@ -628,7 +619,7 @@ class MicropubControllerTest extends TestCase
->assertStatus(500); ->assertStatus(500);
} }
/** @test */ #[Test]
public function micropubClientApiRequestWithTokenWithInsufficientScopeReturnsError(): void public function micropubClientApiRequestWithTokenWithInsufficientScopeReturnsError(): void
{ {
$response = $this->postJson( $response = $this->postJson(
@ -647,7 +638,7 @@ class MicropubControllerTest extends TestCase
->assertJson(['error' => 'insufficient_scope']); ->assertJson(['error' => 'insufficient_scope']);
} }
/** @test */ #[Test]
public function micropubClientApiRequestCanReplaceNoteSyndicationTargets(): void public function micropubClientApiRequestCanReplaceNoteSyndicationTargets(): void
{ {
$note = Note::factory()->create(); $note = Note::factory()->create();
@ -674,7 +665,7 @@ class MicropubControllerTest extends TestCase
]); ]);
} }
/** @test */ #[Test]
public function micropubClientWebRequestCanEncodeTokenWithinTheForm(): void public function micropubClientWebRequestCanEncodeTokenWithinTheForm(): void
{ {
$faker = Factory::create(); $faker = Factory::create();
@ -692,7 +683,7 @@ class MicropubControllerTest extends TestCase
$this->assertDatabaseHas('notes', ['note' => $note]); $this->assertDatabaseHas('notes', ['note' => $note]);
} }
/** @test */ #[Test]
public function micropubClientApiRequestCreatesArticlesWhenItIncludesTheNameProperty(): void public function micropubClientApiRequestCreatesArticlesWhenItIncludesTheNameProperty(): void
{ {
$faker = Factory::create(); $faker = Factory::create();

View file

@ -11,6 +11,7 @@ use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Queue; use Illuminate\Support\Facades\Queue;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
use Tests\TestToken; use Tests\TestToken;
@ -19,7 +20,7 @@ class MicropubMediaTest extends TestCase
use RefreshDatabase; use RefreshDatabase;
use TestToken; use TestToken;
/** @test */ #[Test]
public function emptyResponseForLastUploadWhenNoneFound(): void public function emptyResponseForLastUploadWhenNoneFound(): void
{ {
// Make sure theres no media // Make sure theres no media
@ -33,7 +34,7 @@ class MicropubMediaTest extends TestCase
$response->assertJson(['url' => null]); $response->assertJson(['url' => null]);
} }
/** @test */ #[Test]
public function getRequestWithInvalidTokenReturnsErrorResponse(): void public function getRequestWithInvalidTokenReturnsErrorResponse(): void
{ {
$response = $this->get( $response = $this->get(
@ -44,7 +45,7 @@ class MicropubMediaTest extends TestCase
$response->assertJsonFragment(['error_description' => 'The provided token did not pass validation']); $response->assertJsonFragment(['error_description' => 'The provided token did not pass validation']);
} }
/** @test */ #[Test]
public function getRequestWithTokenWithoutScopeReturnsErrorResponse(): void public function getRequestWithTokenWithoutScopeReturnsErrorResponse(): void
{ {
$response = $this->get( $response = $this->get(
@ -55,7 +56,7 @@ class MicropubMediaTest extends TestCase
$response->assertJsonFragment(['error_description' => 'The provided token has no scopes']); $response->assertJsonFragment(['error_description' => 'The provided token has no scopes']);
} }
/** @test */ #[Test]
public function getRequestWithTokenWithInsufficientScopeReturnsErrorResponse(): void public function getRequestWithTokenWithInsufficientScopeReturnsErrorResponse(): void
{ {
$response = $this->get( $response = $this->get(
@ -66,7 +67,7 @@ class MicropubMediaTest extends TestCase
$response->assertJsonFragment(['error_description' => 'The tokens scope does not have the necessary requirements.']); $response->assertJsonFragment(['error_description' => 'The tokens scope does not have the necessary requirements.']);
} }
/** @test */ #[Test]
public function emptyGetRequestWithTokenReceivesOkResponse(): void public function emptyGetRequestWithTokenReceivesOkResponse(): void
{ {
$response = $this->get( $response = $this->get(
@ -77,7 +78,7 @@ class MicropubMediaTest extends TestCase
$response->assertJson(['status' => 'OK']); $response->assertJson(['status' => 'OK']);
} }
/** @test */ #[Test]
public function clientCanListLastUpload(): void public function clientCanListLastUpload(): void
{ {
Queue::fake(); Queue::fake();
@ -102,11 +103,11 @@ class MicropubMediaTest extends TestCase
$lastUploadResponse->assertJson(['url' => $response->headers->get('Location')]); $lastUploadResponse->assertJson(['url' => $response->headers->get('Location')]);
// now remove file // now remove file
unlink(storage_path('app/media/') . $filename); unlink(storage_path('app/private/media/') . $filename);
$this->removeDirIfEmpty(storage_path('app/media')); $this->removeDirIfEmpty(storage_path('app/private/media'));
} }
/** @test */ #[Test]
public function clientCanSourceUploads(): void public function clientCanSourceUploads(): void
{ {
Queue::fake(); Queue::fake();
@ -134,11 +135,11 @@ class MicropubMediaTest extends TestCase
]]]); ]]]);
// now remove file // now remove file
unlink(storage_path('app/media/') . $filename); unlink(storage_path('app/private/media/') . $filename);
$this->removeDirIfEmpty(storage_path('app/media')); $this->removeDirIfEmpty(storage_path('app/private/media'));
} }
/** @test */ #[Test]
public function clientCanSourceUploadsWithLimit(): void public function clientCanSourceUploadsWithLimit(): void
{ {
Queue::fake(); Queue::fake();
@ -168,11 +169,11 @@ class MicropubMediaTest extends TestCase
$this->assertCount(1, json_decode($sourceUploadResponse->getContent(), true)['items']); $this->assertCount(1, json_decode($sourceUploadResponse->getContent(), true)['items']);
// now remove file // now remove file
unlink(storage_path('app/media/') . $filename); unlink(storage_path('app/private/media/') . $filename);
$this->removeDirIfEmpty(storage_path('app/media')); $this->removeDirIfEmpty(storage_path('app/private/media'));
} }
/** @test */ #[Test]
public function mediaEndpointUploadRequiresFile(): void public function mediaEndpointUploadRequiresFile(): void
{ {
$response = $this->post( $response = $this->post(
@ -188,7 +189,7 @@ class MicropubMediaTest extends TestCase
]); ]);
} }
/** @test */ #[Test]
public function errorResponseForUnknownQValue(): void public function errorResponseForUnknownQValue(): void
{ {
$response = $this->get( $response = $this->get(
@ -199,7 +200,7 @@ class MicropubMediaTest extends TestCase
$response->assertJson(['error' => 'invalid_request']); $response->assertJson(['error' => 'invalid_request']);
} }
/** @test */ #[Test]
public function optionsRequestReturnsCorsResponse(): void public function optionsRequestReturnsCorsResponse(): void
{ {
$response = $this->options('/api/media'); $response = $this->options('/api/media');
@ -208,7 +209,7 @@ class MicropubMediaTest extends TestCase
$response->assertHeader('access-control-allow-origin', '*'); $response->assertHeader('access-control-allow-origin', '*');
} }
/** @test */ #[Test]
public function mediaEndpointRequestWithInvalidTokenReturns400Response(): void public function mediaEndpointRequestWithInvalidTokenReturns400Response(): void
{ {
$response = $this->post( $response = $this->post(
@ -220,7 +221,7 @@ class MicropubMediaTest extends TestCase
$response->assertJsonFragment(['error_description' => 'The provided token did not pass validation']); $response->assertJsonFragment(['error_description' => 'The provided token did not pass validation']);
} }
/** @test */ #[Test]
public function mediaEndpointRequestWithTokenWithNoScopeReturns400Response(): void public function mediaEndpointRequestWithTokenWithNoScopeReturns400Response(): void
{ {
$response = $this->post( $response = $this->post(
@ -232,7 +233,7 @@ class MicropubMediaTest extends TestCase
$response->assertJsonFragment(['error_description' => 'The provided token has no scopes']); $response->assertJsonFragment(['error_description' => 'The provided token has no scopes']);
} }
/** @test */ #[Test]
public function mediaEndpointRequestWithInsufficientTokenScopesReturns401Response(): void public function mediaEndpointRequestWithInsufficientTokenScopesReturns401Response(): void
{ {
$response = $this->post( $response = $this->post(
@ -246,7 +247,7 @@ class MicropubMediaTest extends TestCase
]); ]);
} }
/** @test */ #[Test]
public function mediaEndpointUploadFile(): void public function mediaEndpointUploadFile(): void
{ {
Queue::fake(); Queue::fake();
@ -265,11 +266,11 @@ class MicropubMediaTest extends TestCase
Queue::assertPushed(ProcessMedia::class); Queue::assertPushed(ProcessMedia::class);
Storage::disk('local')->assertExists($filename); Storage::disk('local')->assertExists($filename);
// now remove file // now remove file
unlink(storage_path('app/') . $filename); unlink(storage_path('app/private/') . $filename);
$this->removeDirIfEmpty(storage_path('app/media')); $this->removeDirIfEmpty(storage_path('app/private/media'));
} }
/** @test */ #[Test]
public function mediaEndpointUploadAudioFile(): void public function mediaEndpointUploadAudioFile(): void
{ {
Queue::fake(); Queue::fake();
@ -288,11 +289,11 @@ class MicropubMediaTest extends TestCase
Queue::assertPushed(ProcessMedia::class); Queue::assertPushed(ProcessMedia::class);
Storage::disk('local')->assertExists($filename); Storage::disk('local')->assertExists($filename);
// now remove file // now remove file
unlink(storage_path('app/') . $filename); unlink(storage_path('app/private/') . $filename);
$this->removeDirIfEmpty(storage_path('app/media')); $this->removeDirIfEmpty(storage_path('app/private/media'));
} }
/** @test */ #[Test]
public function mediaEndpointUploadVideoFile(): void public function mediaEndpointUploadVideoFile(): void
{ {
Queue::fake(); Queue::fake();
@ -311,11 +312,11 @@ class MicropubMediaTest extends TestCase
Queue::assertPushed(ProcessMedia::class); Queue::assertPushed(ProcessMedia::class);
Storage::disk('local')->assertExists($filename); Storage::disk('local')->assertExists($filename);
// now remove file // now remove file
unlink(storage_path('app/') . $filename); unlink(storage_path('app/private/') . $filename);
$this->removeDirIfEmpty(storage_path('app/media')); $this->removeDirIfEmpty(storage_path('app/private/media'));
} }
/** @test */ #[Test]
public function mediaEndpointUploadDocumentFile(): void public function mediaEndpointUploadDocumentFile(): void
{ {
Queue::fake(); Queue::fake();
@ -333,11 +334,11 @@ class MicropubMediaTest extends TestCase
Queue::assertPushed(ProcessMedia::class); Queue::assertPushed(ProcessMedia::class);
Storage::disk('local')->assertExists($filename); Storage::disk('local')->assertExists($filename);
// now remove file // now remove file
unlink(storage_path('app/') . $filename); unlink(storage_path('app/private/') . $filename);
$this->removeDirIfEmpty(storage_path('app/media')); $this->removeDirIfEmpty(storage_path('app/private/media'));
} }
/** @test */ #[Test]
public function mediaEndpointUploadInvalidFileReturnsError(): void public function mediaEndpointUploadInvalidFileReturnsError(): void
{ {
Queue::fake(); Queue::fake();

View file

@ -6,6 +6,7 @@ namespace Tests\Feature;
use App\Models\Note; use App\Models\Note;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class NotesControllerTest extends TestCase class NotesControllerTest extends TestCase
@ -15,9 +16,8 @@ class NotesControllerTest extends TestCase
/** /**
* Test the `/notes` page returns 200, this should * Test the `/notes` page returns 200, this should
* mean the database is being hit. * mean the database is being hit.
*
* @test
*/ */
#[Test]
public function notesPageLoads(): void public function notesPageLoads(): void
{ {
$response = $this->get('/notes'); $response = $this->get('/notes');
@ -26,9 +26,8 @@ class NotesControllerTest extends TestCase
/** /**
* Test a specific note. * Test a specific note.
*
* @test
*/ */
#[Test]
public function specificNotePageLoads(): void public function specificNotePageLoads(): void
{ {
$note = Note::factory()->create(); $note = Note::factory()->create();
@ -46,9 +45,8 @@ class NotesControllerTest extends TestCase
/** /**
* Test that `/note/{decID}` redirects to `/notes/{nb60id}`. * Test that `/note/{decID}` redirects to `/notes/{nb60id}`.
*
* @test
*/ */
#[Test]
public function oldNoteUrlsRedirect(): void public function oldNoteUrlsRedirect(): void
{ {
$note = Note::factory()->create(); $note = Note::factory()->create();
@ -58,23 +56,22 @@ class NotesControllerTest extends TestCase
/** /**
* Visit the tagged page and check the tag view data. * Visit the tagged page and check the tag view data.
*
* @test
*/ */
#[Test]
public function taggedNotesPageLoads(): void public function taggedNotesPageLoads(): void
{ {
$response = $this->get('/notes/tagged/beer'); $response = $this->get('/notes/tagged/beer');
$response->assertViewHas('tag', 'beer'); $response->assertViewHas('tag', 'beer');
} }
/** @test */ #[Test]
public function unknownNoteGives404(): void public function unknownNoteGives404(): void
{ {
$response = $this->get('/notes/112233'); $response = $this->get('/notes/112233');
$response->assertNotFound(); $response->assertNotFound();
} }
/** @test */ #[Test]
public function checkNoteIdNotOutOfRange(): void public function checkNoteIdNotOutOfRange(): void
{ {
$response = $this->get('/notes/photou-photologo'); $response = $this->get('/notes/photou-photologo');

View file

@ -6,6 +6,7 @@ namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
use Tests\TestToken; use Tests\TestToken;
@ -14,7 +15,7 @@ class OwnYourGramTest extends TestCase
use RefreshDatabase; use RefreshDatabase;
use TestToken; use TestToken;
/** @test */ #[Test]
public function postingInstagramUrlSavesMediaPath(): void public function postingInstagramUrlSavesMediaPath(): void
{ {
$response = $this->json( $response = $this->json(

View file

@ -9,6 +9,7 @@ use Illuminate\FileSystem\FileSystem;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Artisan;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class ParseCachedWebMentionsTest extends TestCase class ParseCachedWebMentionsTest extends TestCase
@ -25,7 +26,7 @@ class ParseCachedWebMentionsTest extends TestCase
copy(__DIR__ . '/../tantek.html', storage_path('HTML') . '/http/tantek.com/index.html'); copy(__DIR__ . '/../tantek.html', storage_path('HTML') . '/http/tantek.com/index.html');
} }
/** @test */ #[Test]
public function parseWebmentionHtml(): void public function parseWebmentionHtml(): void
{ {
$webmentionAaron = WebMention::factory()->create([ $webmentionAaron = WebMention::factory()->create([

View file

@ -6,6 +6,7 @@ namespace Tests\Feature;
use App\Models\Place; use App\Models\Place;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class PlacesTest extends TestCase class PlacesTest extends TestCase
@ -14,9 +15,8 @@ class PlacesTest extends TestCase
/** /**
* Test the `/places` page for OK response. * Test the `/places` page for OK response.
*
* @test
*/ */
#[Test]
public function placesPageLoads(): void public function placesPageLoads(): void
{ {
$response = $this->get('/places'); $response = $this->get('/places');
@ -25,9 +25,8 @@ class PlacesTest extends TestCase
/** /**
* Test a specific place. * Test a specific place.
*
* @test
*/ */
#[Test]
public function singlePlacePageLoads(): void public function singlePlacePageLoads(): void
{ {
$place = Place::factory()->create(); $place = Place::factory()->create();
@ -35,7 +34,7 @@ class PlacesTest extends TestCase
$response->assertViewHas('place', $place); $response->assertViewHas('place', $place);
} }
/** @test */ #[Test]
public function unknownPlaceGives404() public function unknownPlaceGives404()
{ {
$response = $this->get('/places/unknown'); $response = $this->get('/places/unknown');

View file

@ -9,13 +9,14 @@ use App\Models\WebMention;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Queue; use Illuminate\Support\Facades\Queue;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class ReDownloadWebMentionsTest extends TestCase class ReDownloadWebMentionsTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
/** @test */ #[Test]
public function downloadJobGetsQueued(): void public function downloadJobGetsQueued(): void
{ {
Queue::fake(); Queue::fake();

View file

@ -5,11 +5,12 @@ declare(strict_types=1);
namespace Tests\Feature; namespace Tests\Feature;
use App\Models\Note; use App\Models\Note;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class SearchTest extends TestCase class SearchTest extends TestCase
{ {
/** @test */ #[Test]
public function searchEndpointReturnsResults(): void public function searchEndpointReturnsResults(): void
{ {
Note::factory(10)->create(); Note::factory(10)->create();

View file

@ -4,32 +4,33 @@ declare(strict_types=1);
namespace Tests\Feature; namespace Tests\Feature;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class ShortURLsControllerTest extends TestCase class ShortURLsControllerTest extends TestCase
{ {
/** @test */ #[Test]
public function shortDomainRedirectsToLongDomain(): void public function shortDomainRedirectsToLongDomain(): void
{ {
$response = $this->get('https://' . config('url.shorturl')); $response = $this->get('https://' . config('url.shorturl'));
$response->assertRedirect(config('app.url')); $response->assertRedirect(config('app.url'));
} }
/** @test */ #[Test]
public function shortDomainSlashAtRedirectsToTwitter(): void public function shortDomainSlashAtRedirectsToTwitter(): void
{ {
$response = $this->get('https://' . config('url.shorturl') . '/@'); $response = $this->get('https://' . config('url.shorturl') . '/@');
$response->assertRedirect('https://twitter.com/jonnybarnes'); $response->assertRedirect('https://twitter.com/jonnybarnes');
} }
/** @test */ #[Test]
public function shortDomainSlashTRedirectsToLongDomainSlashNotes(): void public function shortDomainSlashTRedirectsToLongDomainSlashNotes(): void
{ {
$response = $this->get('https://' . config('url.shorturl') . '/t/E'); $response = $this->get('https://' . config('url.shorturl') . '/t/E');
$response->assertRedirect(config('app.url') . '/notes/E'); $response->assertRedirect(config('app.url') . '/notes/E');
} }
/** @test */ #[Test]
public function shortDomainSlashBRedirectsToLongDomainSlashBlog(): void public function shortDomainSlashBRedirectsToLongDomainSlashBlog(): void
{ {
$response = $this->get('https://' . config('url.shorturl') . '/b/1'); $response = $this->get('https://' . config('url.shorturl') . '/b/1');

View file

@ -8,6 +8,7 @@ use App\Jobs\SendWebMentions;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Queue; use Illuminate\Support\Facades\Queue;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
use Tests\TestToken; use Tests\TestToken;
@ -18,9 +19,8 @@ class SwarmTest extends TestCase
/** /**
* Given a check in to Foursquare, this is the content Ownyourswarm will post to us. * Given a check in to Foursquare, this is the content Ownyourswarm will post to us.
*
* @test
*/ */
#[Test]
public function mockedOwnyourswarmRequestWithFoursquare(): void public function mockedOwnyourswarmRequestWithFoursquare(): void
{ {
Queue::fake(); Queue::fake();
@ -66,9 +66,8 @@ class SwarmTest extends TestCase
/** /**
* This request would actually come from another client than OwnYourSwarm, but were testing * This request would actually come from another client than OwnYourSwarm, but were testing
* OpenStreetMap data. * OpenStreetMap data.
*
* @test
*/ */
#[Test]
public function mockedOwnyourswarmRequestWithOsm(): void public function mockedOwnyourswarmRequestWithOsm(): void
{ {
Queue::fake(); Queue::fake();
@ -109,9 +108,8 @@ class SwarmTest extends TestCase
/** /**
* This request would actually come from another client than OwnYourSwarm, as that would include a Foursquare URL * This request would actually come from another client than OwnYourSwarm, as that would include a Foursquare URL
*
* @test
*/ */
#[Test]
public function mockedOwnyourswarmRequestWithoutKnownExternalUrl(): void public function mockedOwnyourswarmRequestWithoutKnownExternalUrl(): void
{ {
Queue::fake(); Queue::fake();
@ -150,7 +148,7 @@ class SwarmTest extends TestCase
Queue::assertPushed(SendWebMentions::class); Queue::assertPushed(SendWebMentions::class);
} }
/** @test */ #[Test]
public function mockedOwnyourswarmRequestWithNoTextContent(): void public function mockedOwnyourswarmRequestWithNoTextContent(): void
{ {
$response = $this->json( $response = $this->json(
@ -187,7 +185,7 @@ class SwarmTest extends TestCase
$this->get($response->__get('headers')->get('location'))->assertSee('📍'); $this->get($response->__get('headers')->get('location'))->assertSee('📍');
} }
/** @test */ #[Test]
public function mockedOwnyourswarmRequestSavesJustThePostWhenAnErrorOccursInTheCheckinData(): void public function mockedOwnyourswarmRequestSavesJustThePostWhenAnErrorOccursInTheCheckinData(): void
{ {
Queue::fake(); Queue::fake();
@ -225,7 +223,7 @@ class SwarmTest extends TestCase
Queue::assertPushed(SendWebMentions::class); Queue::assertPushed(SendWebMentions::class);
} }
/** @test */ #[Test]
public function mockedOwnyourswarmRequestWithHAdrLocation(): void public function mockedOwnyourswarmRequestWithHAdrLocation(): void
{ {
Queue::fake(); Queue::fake();
@ -271,7 +269,7 @@ class SwarmTest extends TestCase
Queue::assertPushed(SendWebMentions::class); Queue::assertPushed(SendWebMentions::class);
} }
/** @test */ #[Test]
public function ownyourswarmCheckinTestUsingRealData(): void public function ownyourswarmCheckinTestUsingRealData(): void
{ {
$response = $this->json( $response = $this->json(

View file

@ -9,6 +9,7 @@ use DateTimeImmutable;
use Lcobucci\JWT\Configuration; use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer\Key\InMemory; use Lcobucci\JWT\Signer\Key\InMemory;
use Lcobucci\JWT\Validation\RequiredConstraintsViolated; use Lcobucci\JWT\Validation\RequiredConstraintsViolated;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class TokenServiceTest extends TestCase class TokenServiceTest extends TestCase
@ -16,9 +17,8 @@ class TokenServiceTest extends TestCase
/** /**
* Given the token is dependent on a random nonce, the time of creation and * Given the token is dependent on a random nonce, the time of creation and
* the APP_KEY, to test, we shall create a token, and then verify it. * the APP_KEY, to test, we shall create a token, and then verify it.
*
* @test
*/ */
#[Test]
public function tokenserviceCreatesAndValidatesTokens(): void public function tokenserviceCreatesAndValidatesTokens(): void
{ {
$tokenService = new TokenService; $tokenService = new TokenService;
@ -37,11 +37,7 @@ class TokenServiceTest extends TestCase
$this->assertSame($data, $validData); $this->assertSame($data, $validData);
} }
/** #[Test]
* @test
*
* @throws \Exception
*/
public function tokensWithDifferentSigningKeyThrowsException(): void public function tokensWithDifferentSigningKeyThrowsException(): void
{ {
$this->expectException(RequiredConstraintsViolated::class); $this->expectException(RequiredConstraintsViolated::class);

View file

@ -8,13 +8,14 @@ use App\Jobs\ProcessWebMention;
use App\Models\Note; use App\Models\Note;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Queue; use Illuminate\Support\Facades\Queue;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class WebMentionsControllerTest extends TestCase class WebMentionsControllerTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
/** @test */ #[Test]
public function webmentionEndpointCanServeBrowserRequest(): void public function webmentionEndpointCanServeBrowserRequest(): void
{ {
$response = $this->get('/webmention'); $response = $this->get('/webmention');
@ -23,9 +24,8 @@ class WebMentionsControllerTest extends TestCase
/** /**
* Test webmentions without source and target are rejected. * Test webmentions without source and target are rejected.
*
* @test
*/ */
#[Test]
public function webmentionsWithoutSourceAndTargetAreRejected(): void public function webmentionsWithoutSourceAndTargetAreRejected(): void
{ {
$response = $this->call('POST', '/webmention', ['source' => 'https://example.org/post/123']); $response = $this->call('POST', '/webmention', ['source' => 'https://example.org/post/123']);
@ -36,9 +36,8 @@ class WebMentionsControllerTest extends TestCase
* Test invalid target gives a 400 response. * Test invalid target gives a 400 response.
* *
* In this case an invalid target is a URL that doesnt exist on our domain. * In this case an invalid target is a URL that doesnt exist on our domain.
*
* @test
*/ */
#[Test]
public function invalidTargetReturnsErrorResponse(): void public function invalidTargetReturnsErrorResponse(): void
{ {
$response = $this->call('POST', '/webmention', [ $response = $this->call('POST', '/webmention', [
@ -50,9 +49,8 @@ class WebMentionsControllerTest extends TestCase
/** /**
* Test blog target gets a 501 response due to our not supporting it. * Test blog target gets a 501 response due to our not supporting it.
*
* @test
*/ */
#[Test]
public function blogTargetReturns501Response(): void public function blogTargetReturns501Response(): void
{ {
$response = $this->call('POST', '/webmention', [ $response = $this->call('POST', '/webmention', [
@ -64,9 +62,8 @@ class WebMentionsControllerTest extends TestCase
/** /**
* Test that a non-existent note gives a 400 response. * Test that a non-existent note gives a 400 response.
*
* @test
*/ */
#[Test]
public function nonexistentNoteReturnsErrorResponse(): void public function nonexistentNoteReturnsErrorResponse(): void
{ {
$response = $this->call('POST', '/webmention', [ $response = $this->call('POST', '/webmention', [
@ -76,7 +73,7 @@ class WebMentionsControllerTest extends TestCase
$response->assertStatus(400); $response->assertStatus(400);
} }
/** @test */ #[Test]
public function legitimateWebmentionTriggersProcessWebmentionJob(): void public function legitimateWebmentionTriggersProcessWebmentionJob(): void
{ {
Queue::fake(); Queue::fake();

View file

@ -7,13 +7,14 @@ namespace Tests\Unit;
use App\Models\Article; use App\Models\Article;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class ArticlesTest extends TestCase class ArticlesTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
/** @test */ #[Test]
public function titleSlugIsGeneratedAutomatically(): void public function titleSlugIsGeneratedAutomatically(): void
{ {
$article = new Article; $article = new Article;
@ -24,7 +25,7 @@ class ArticlesTest extends TestCase
$this->assertEquals('my-title', $article->titleurl); $this->assertEquals('my-title', $article->titleurl);
} }
/** @test */ #[Test]
public function markdownContentIsConverted(): void public function markdownContentIsConverted(): void
{ {
$article = new Article; $article = new Article;
@ -33,7 +34,7 @@ class ArticlesTest extends TestCase
$this->assertEquals('<p>Some <em>markdown</em></p>' . PHP_EOL, $article->html); $this->assertEquals('<p>Some <em>markdown</em></p>' . PHP_EOL, $article->html);
} }
/** @test */ #[Test]
public function weGenerateTheDifferentTimeAttributes(): void public function weGenerateTheDifferentTimeAttributes(): void
{ {
$article = Article::create([ $article = Article::create([
@ -47,7 +48,7 @@ class ArticlesTest extends TestCase
$this->assertEquals($article->pubdate, $article->updated_at->toRSSString()); $this->assertEquals($article->pubdate, $article->updated_at->toRSSString());
} }
/** @test */ #[Test]
public function weGenerateTheArticleLinkFromTheSlug(): void public function weGenerateTheArticleLinkFromTheSlug(): void
{ {
$article = Article::create([ $article = Article::create([
@ -62,7 +63,7 @@ class ArticlesTest extends TestCase
); );
} }
/** @test */ #[Test]
public function dateScopeReturnsExpectedArticles(): void public function dateScopeReturnsExpectedArticles(): void
{ {
Article::factory()->create([ Article::factory()->create([
@ -81,7 +82,7 @@ class ArticlesTest extends TestCase
$this->assertCount(2, $emptyScope); $this->assertCount(2, $emptyScope);
} }
/** @test */ #[Test]
public function dateScopeReturnsExpectedArticlesForDecember(): void public function dateScopeReturnsExpectedArticlesForDecember(): void
{ {
Article::factory()->create([ Article::factory()->create([

View file

@ -10,14 +10,15 @@ use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack; use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response; use GuzzleHttp\Psr7\Response;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class BookmarksTest extends TestCase class BookmarksTest extends TestCase
{ {
/** /*
* @test * @\test
* *
* @group puppeteer * @\group puppeteer
* *
public function takeScreenshotOfDuckDuckGo() public function takeScreenshotOfDuckDuckGo()
{ {
@ -25,7 +26,7 @@ class BookmarksTest extends TestCase
$this->assertTrue(file_exists(public_path() . '/assets/img/bookmarks/' . $uuid . '.png')); $this->assertTrue(file_exists(public_path() . '/assets/img/bookmarks/' . $uuid . '.png'));
}*/ }*/
/** @test */ #[Test]
public function archiveLinkMethodCallsArchiveService(): void public function archiveLinkMethodCallsArchiveService(): void
{ {
$mock = new MockHandler([ $mock = new MockHandler([
@ -38,7 +39,7 @@ class BookmarksTest extends TestCase
$this->assertEquals('/web/1234/example.org', $url); $this->assertEquals('/web/1234/example.org', $url);
} }
/** @test */ #[Test]
public function archiveLinkMethodThrowsAnExceptionOnError(): void public function archiveLinkMethodThrowsAnExceptionOnError(): void
{ {
$this->expectException(InternetArchiveException::class); $this->expectException(InternetArchiveException::class);
@ -52,7 +53,7 @@ class BookmarksTest extends TestCase
(new BookmarkService)->getArchiveLink('https://example.org'); (new BookmarkService)->getArchiveLink('https://example.org');
} }
/** @test */ #[Test]
public function archiveLinkMethodThrowsAnExceptionIfNoLocationReturned(): void public function archiveLinkMethodThrowsAnExceptionIfNoLocationReturned(): void
{ {
$this->expectException(InternetArchiveException::class); $this->expectException(InternetArchiveException::class);

View file

@ -4,28 +4,27 @@ declare(strict_types=1);
namespace Tests\Unit; namespace Tests\Unit;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class HelpersTest extends TestCase class HelpersTest extends TestCase
{ {
/** @test */ #[Test]
public function normalizeUrlIsIdempotent(): void public function normalizeUrlIsIdempotent(): void
{ {
$input = 'http://example.org:80/index.php?foo=bar&baz=1'; $input = 'http://example.org:80/index.php?foo=bar&baz=1';
$this->assertEquals(normalize_url(normalize_url($input)), normalize_url($input)); $this->assertEquals(normalize_url(normalize_url($input)), normalize_url($input));
} }
/** #[Test]
* @test #[DataProvider('urlProvider')]
*
* @dataProvider urlProvider
*/
public function normalizeUrlOnDataProvider(string $input, string $output): void public function normalizeUrlOnDataProvider(string $input, string $output): void
{ {
$this->assertEquals($output, normalize_url($input)); $this->assertEquals($output, normalize_url($input));
} }
/** @test */ #[Test]
public function prettyPrintJson(): void public function prettyPrintJson(): void
{ {
// phpcs:disable Generic.Files.LineLength.TooLong // phpcs:disable Generic.Files.LineLength.TooLong

View file

@ -6,13 +6,14 @@ namespace Tests\Unit\Jobs;
use App\Jobs\AddClientToDatabase; use App\Jobs\AddClientToDatabase;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class AddClientToDatabaseJobTest extends TestCase class AddClientToDatabaseJobTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
/** @test */ #[Test]
public function clientIsAddedToDatabaseByJob(): void public function clientIsAddedToDatabaseByJob(): void
{ {
$job = new AddClientToDatabase('https://example.org/client'); $job = new AddClientToDatabase('https://example.org/client');

View file

@ -10,6 +10,7 @@ use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack; use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response; use GuzzleHttp\Psr7\Response;
use Illuminate\FileSystem\FileSystem; use Illuminate\FileSystem\FileSystem;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class DownloadWebMentionJobTest extends TestCase class DownloadWebMentionJobTest extends TestCase
@ -23,7 +24,7 @@ class DownloadWebMentionJobTest extends TestCase
parent::tearDown(); parent::tearDown();
} }
/** @test */ #[Test]
public function htmlIsSavedByJob(): void public function htmlIsSavedByJob(): void
{ {
$this->assertFileDoesNotExist(storage_path('HTML/https')); $this->assertFileDoesNotExist(storage_path('HTML/https'));
@ -51,7 +52,7 @@ class DownloadWebMentionJobTest extends TestCase
$this->assertFileDoesNotExist(storage_path('HTML/https/example.org/reply') . '/1.' . date('Y-m-d') . '.backup'); $this->assertFileDoesNotExist(storage_path('HTML/https/example.org/reply') . '/1.' . date('Y-m-d') . '.backup');
} }
/** @test */ #[Test]
public function htmlAndBackupSavedByJob(): void public function htmlAndBackupSavedByJob(): void
{ {
$this->assertFileDoesNotExist(storage_path('HTML/https')); $this->assertFileDoesNotExist(storage_path('HTML/https'));
@ -86,7 +87,7 @@ class DownloadWebMentionJobTest extends TestCase
$this->assertFileExists(storage_path('HTML/https/example.org/reply') . '/1.' . date('Y-m-d') . '.backup'); $this->assertFileExists(storage_path('HTML/https/example.org/reply') . '/1.' . date('Y-m-d') . '.backup');
} }
/** @test */ #[Test]
public function indexHtmlFileIsSavedByJobForUrlsEndingWithSlash(): void public function indexHtmlFileIsSavedByJobForUrlsEndingWithSlash(): void
{ {
$this->assertFileDoesNotExist(storage_path('HTML/https')); $this->assertFileDoesNotExist(storage_path('HTML/https'));

View file

@ -11,13 +11,14 @@ use App\Models\Bookmark;
use App\Services\BookmarkService; use App\Services\BookmarkService;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Queue; use Illuminate\Support\Facades\Queue;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class ProcessBookmarkJobTest extends TestCase class ProcessBookmarkJobTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
/** @test */ #[Test]
public function archiveLinkIsSavedByJobAndScreenshotJobIsQueued(): void public function archiveLinkIsSavedByJobAndScreenshotJobIsQueued(): void
{ {
Queue::fake(); Queue::fake();
@ -38,7 +39,7 @@ class ProcessBookmarkJobTest extends TestCase
Queue::assertPushed(SaveScreenshot::class); Queue::assertPushed(SaveScreenshot::class);
} }
/** @test */ #[Test]
public function archiveLinkSavedAsNullWhenExceptionThrown(): void public function archiveLinkSavedAsNullWhenExceptionThrown(): void
{ {
Queue::fake(); Queue::fake();

View file

@ -7,11 +7,12 @@ namespace Tests\Unit\Jobs;
use App\Jobs\ProcessMedia; use App\Jobs\ProcessMedia;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Intervention\Image\ImageManager; use Intervention\Image\ImageManager;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class ProcessMediaJobTest extends TestCase class ProcessMediaJobTest extends TestCase
{ {
/** @test */ #[Test]
public function nonMediaFilesAreNotSaved(): void public function nonMediaFilesAreNotSaved(): void
{ {
$manager = app()->make(ImageManager::class); $manager = app()->make(ImageManager::class);
@ -22,7 +23,7 @@ class ProcessMediaJobTest extends TestCase
$this->assertFileDoesNotExist(storage_path('app/media/') . 'file.txt'); $this->assertFileDoesNotExist(storage_path('app/media/') . 'file.txt');
} }
/** @test */ #[Test]
public function smallImagesAreNotResized(): void public function smallImagesAreNotResized(): void
{ {
$manager = app()->make(ImageManager::class); $manager = app()->make(ImageManager::class);
@ -37,7 +38,7 @@ class ProcessMediaJobTest extends TestCase
Storage::disk('local')->delete('public/media'); Storage::disk('local')->delete('public/media');
} }
/** @test */ #[Test]
public function largeImagesHaveSmallerImagesCreated(): void public function largeImagesHaveSmallerImagesCreated(): void
{ {
$manager = app()->make(ImageManager::class); $manager = app()->make(ImageManager::class);
@ -45,16 +46,17 @@ class ProcessMediaJobTest extends TestCase
$job = new ProcessMedia('test-image.jpg'); $job = new ProcessMedia('test-image.jpg');
$job->handle($manager); $job->handle($manager);
Storage::disk('local')->assertExists('public/media/test-image.jpg'); // These need to look in public disk
Storage::disk('local')->assertExists('public/media/test-image-small.jpg'); Storage::disk('public')->assertExists('media/test-image.jpg');
Storage::disk('local')->assertExists('public/media/test-image-medium.jpg'); Storage::disk('public')->assertExists('media/test-image-small.jpg');
Storage::disk('public')->assertExists('media/test-image-medium.jpg');
$this->assertFileDoesNotExist(storage_path('app/media/') . 'test-image.jpg'); $this->assertFileDoesNotExist(storage_path('app/media/') . 'test-image.jpg');
// Tidy up files created by the job // Tidy up files created by the job
Storage::disk('local')->delete('public/media/test-image.jpg'); Storage::disk('public')->delete('media/test-image.jpg');
Storage::disk('local')->delete('public/media/test-image-small.jpg'); Storage::disk('public')->delete('media/test-image-small.jpg');
Storage::disk('local')->delete('public/media/test-image-medium.jpg'); Storage::disk('public')->delete('media/test-image-medium.jpg');
$this->removeDirIfEmpty(storage_path('app/public/media')); $this->removeDirIfEmpty(storage_path('app/public/media'));
$this->removeDirIfEmpty(storage_path('app/media')); $this->removeDirIfEmpty(storage_path('app/media'));
} }

View file

@ -17,6 +17,7 @@ use Illuminate\FileSystem\FileSystem;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Queue; use Illuminate\Support\Facades\Queue;
use Jonnybarnes\WebmentionsParser\Parser; use Jonnybarnes\WebmentionsParser\Parser;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class ProcessWebMentionJobTest extends TestCase class ProcessWebMentionJobTest extends TestCase
@ -32,7 +33,7 @@ class ProcessWebMentionJobTest extends TestCase
parent::tearDown(); parent::tearDown();
} }
/** @test */ #[Test]
public function failureGettingWebmentionThrowsAnException(): void public function failureGettingWebmentionThrowsAnException(): void
{ {
$this->expectException(RemoteContentNotFoundException::class); $this->expectException(RemoteContentNotFoundException::class);
@ -51,7 +52,7 @@ class ProcessWebMentionJobTest extends TestCase
$job->handle($parser, $client); $job->handle($parser, $client);
} }
/** @test */ #[Test]
public function newWebmentionGetsSavedByJob(): void public function newWebmentionGetsSavedByJob(): void
{ {
Queue::fake(); Queue::fake();
@ -83,7 +84,7 @@ class ProcessWebMentionJobTest extends TestCase
]); ]);
} }
/** @test */ #[Test]
public function existingWebmentionGetsUpdatedByJob(): void public function existingWebmentionGetsUpdatedByJob(): void
{ {
Queue::fake(); Queue::fake();
@ -120,7 +121,7 @@ class ProcessWebMentionJobTest extends TestCase
]); ]);
} }
/** @test */ #[Test]
public function webmentionReplyGetsDeletedWhenReplyToValueChanges(): void public function webmentionReplyGetsDeletedWhenReplyToValueChanges(): void
{ {
$parser = new Parser; $parser = new Parser;
@ -157,7 +158,7 @@ class ProcessWebMentionJobTest extends TestCase
]); ]);
} }
/** @test */ #[Test]
public function webmentionLikeGetsDeletedWhenLikeOfValueChanges(): void public function webmentionLikeGetsDeletedWhenLikeOfValueChanges(): void
{ {
$parser = new Parser; $parser = new Parser;
@ -194,7 +195,7 @@ class ProcessWebMentionJobTest extends TestCase
]); ]);
} }
/** @test */ #[Test]
public function webmentionRepostGetsDeletedWhenRepostOfValueChanges(): void public function webmentionRepostGetsDeletedWhenRepostOfValueChanges(): void
{ {
$parser = new Parser; $parser = new Parser;

View file

@ -11,6 +11,7 @@ use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response; use GuzzleHttp\Psr7\Response;
use Jonnybarnes\WebmentionsParser\Authorship; use Jonnybarnes\WebmentionsParser\Authorship;
use Jonnybarnes\WebmentionsParser\Exceptions\AuthorshipParserException; use Jonnybarnes\WebmentionsParser\Exceptions\AuthorshipParserException;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class SaveProfileImageJobTest extends TestCase class SaveProfileImageJobTest extends TestCase
@ -24,7 +25,7 @@ class SaveProfileImageJobTest extends TestCase
parent::tearDown(); parent::tearDown();
} }
/** @test */ #[Test]
public function authorshipAlgorithmReturnsNullOnException(): void public function authorshipAlgorithmReturnsNullOnException(): void
{ {
$mf = ['items' => []]; $mf = ['items' => []];
@ -36,7 +37,7 @@ class SaveProfileImageJobTest extends TestCase
$this->assertNull($job->handle($authorship)); $this->assertNull($job->handle($authorship));
} }
/** @test */ #[Test]
public function weDoNotProcessTwitterImages(): void public function weDoNotProcessTwitterImages(): void
{ {
$mf = ['items' => []]; $mf = ['items' => []];
@ -54,7 +55,7 @@ class SaveProfileImageJobTest extends TestCase
$this->assertNull($job->handle($authorship)); $this->assertNull($job->handle($authorship));
} }
/** @test */ #[Test]
public function remoteAuthorImagesAreSavedLocally(): void public function remoteAuthorImagesAreSavedLocally(): void
{ {
$mock = new MockHandler([ $mock = new MockHandler([
@ -79,7 +80,7 @@ class SaveProfileImageJobTest extends TestCase
$this->assertFileExists(public_path() . '/assets/profile-images/example.org/image'); $this->assertFileExists(public_path() . '/assets/profile-images/example.org/image');
} }
/** @test */ #[Test]
public function localDefaultAuthorImageIsUsedAsFallback(): void public function localDefaultAuthorImageIsUsedAsFallback(): void
{ {
$mock = new MockHandler([ $mock = new MockHandler([
@ -107,7 +108,7 @@ class SaveProfileImageJobTest extends TestCase
); );
} }
/** @test */ #[Test]
public function weGetUrlFromPhotoObjectIfAltTextIsProvided(): void public function weGetUrlFromPhotoObjectIfAltTextIsProvided(): void
{ {
$mock = new MockHandler([ $mock = new MockHandler([
@ -135,7 +136,7 @@ class SaveProfileImageJobTest extends TestCase
$this->assertFileExists(public_path() . '/assets/profile-images/example.org/image'); $this->assertFileExists(public_path() . '/assets/profile-images/example.org/image');
} }
/** @test */ #[Test]
public function useFirstUrlIfMultipleHomepagesAreProvided(): void public function useFirstUrlIfMultipleHomepagesAreProvided(): void
{ {
$mock = new MockHandler([ $mock = new MockHandler([

View file

@ -13,13 +13,14 @@ use GuzzleHttp\Middleware;
use GuzzleHttp\Psr7\Response; use GuzzleHttp\Psr7\Response;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class SaveScreenshotJobTest extends TestCase class SaveScreenshotJobTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
/** @test */ #[Test]
public function screenshotIsSavedByJob(): void public function screenshotIsSavedByJob(): void
{ {
Storage::fake('public'); Storage::fake('public');
@ -84,7 +85,7 @@ class SaveScreenshotJobTest extends TestCase
Storage::disk('public')->assertExists('/assets/img/bookmarks/' . $bookmark->screenshot . '.png'); Storage::disk('public')->assertExists('/assets/img/bookmarks/' . $bookmark->screenshot . '.png');
} }
/** @test */ #[Test]
public function screenshotJobHandlesUnfinishedTasks(): void public function screenshotJobHandlesUnfinishedTasks(): void
{ {
Storage::fake('public'); Storage::fake('public');

View file

@ -10,11 +10,12 @@ use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack; use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response; use GuzzleHttp\Psr7\Response;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class SendWebMentionJobTest extends TestCase class SendWebMentionJobTest extends TestCase
{ {
/** @test */ #[Test]
public function discoverWebmentionEndpointOnOwnDomain(): void public function discoverWebmentionEndpointOnOwnDomain(): void
{ {
$note = new Note; $note = new Note;
@ -23,7 +24,7 @@ class SendWebMentionJobTest extends TestCase
$this->assertNull($job->discoverWebmentionEndpoint('/notes/tagged/test')); $this->assertNull($job->discoverWebmentionEndpoint('/notes/tagged/test'));
} }
/** @test */ #[Test]
public function discoverWebmentionEndpointFromHeaderLinks(): void public function discoverWebmentionEndpointFromHeaderLinks(): void
{ {
$url = 'https://example.org/webmention'; $url = 'https://example.org/webmention';
@ -38,7 +39,7 @@ class SendWebMentionJobTest extends TestCase
$this->assertEquals($url, $job->discoverWebmentionEndpoint('https://example.org')); $this->assertEquals($url, $job->discoverWebmentionEndpoint('https://example.org'));
} }
/** @test */ #[Test]
public function discoverWebmentionEndpointFromHtmlLinkTags(): void public function discoverWebmentionEndpointFromHtmlLinkTags(): void
{ {
$html = '<link rel="webmention" href="https://example.org/webmention">'; $html = '<link rel="webmention" href="https://example.org/webmention">';
@ -56,7 +57,7 @@ class SendWebMentionJobTest extends TestCase
); );
} }
/** @test */ #[Test]
public function discoverWebmentionEndpointFromLegacyHtmlMarkup(): void public function discoverWebmentionEndpointFromLegacyHtmlMarkup(): void
{ {
$html = '<link rel="http://webmention.org/" href="https://example.org/webmention">'; $html = '<link rel="http://webmention.org/" href="https://example.org/webmention">';
@ -74,14 +75,14 @@ class SendWebMentionJobTest extends TestCase
); );
} }
/** @test */ #[Test]
public function ensureEmptyNoteDoesNotTriggerAnyActions(): void public function ensureEmptyNoteDoesNotTriggerAnyActions(): void
{ {
$job = new SendWebMentions(new Note); $job = new SendWebMentions(new Note);
$this->assertNull($job->handle()); $this->assertNull($job->handle());
} }
/** @test */ #[Test]
public function weResolveRelativeUris(): void public function weResolveRelativeUris(): void
{ {
$uri = '/blog/post'; $uri = '/blog/post';
@ -90,7 +91,7 @@ class SendWebMentionJobTest extends TestCase
$this->assertEquals('https://example.org/blog/post', $job->resolveUri($uri, $base)); $this->assertEquals('https://example.org/blog/post', $job->resolveUri($uri, $base));
} }
/** @test */ #[Test]
public function weSendAWebmentionForANote(): void public function weSendAWebmentionForANote(): void
{ {
$html = '<link rel="http://webmention.org/" href="https://example.org/webmention">'; $html = '<link rel="http://webmention.org/" href="https://example.org/webmention">';
@ -110,7 +111,7 @@ class SendWebMentionJobTest extends TestCase
$this->assertTrue(true); $this->assertTrue(true);
} }
/** @test */ #[Test]
public function linksInNotesCanNotSupportWebmentions(): void public function linksInNotesCanNotSupportWebmentions(): void
{ {
$mock = new MockHandler([ $mock = new MockHandler([

View file

@ -11,13 +11,14 @@ use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware; use GuzzleHttp\Middleware;
use GuzzleHttp\Psr7\Response; use GuzzleHttp\Psr7\Response;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class SyndicateNoteToBlueskyJobTest extends TestCase class SyndicateNoteToBlueskyJobTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
/** @test */ #[Test]
public function weSyndicateNotesToBluesky(): void public function weSyndicateNotesToBluesky(): void
{ {
config(['bridgy.bluesky_token' => 'test']); config(['bridgy.bluesky_token' => 'test']);
@ -38,7 +39,7 @@ class SyndicateNoteToBlueskyJobTest extends TestCase
]); ]);
} }
/** @test */ #[Test]
public function weSyndicateTheOriginalMarkdownToBluesky(): void public function weSyndicateTheOriginalMarkdownToBluesky(): void
{ {
config(['bridgy.bluesky_token' => 'test']); config(['bridgy.bluesky_token' => 'test']);

View file

@ -11,13 +11,14 @@ use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware; use GuzzleHttp\Middleware;
use GuzzleHttp\Psr7\Response; use GuzzleHttp\Psr7\Response;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class SyndicateNoteToMastodonJobTest extends TestCase class SyndicateNoteToMastodonJobTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
/** @test */ #[Test]
public function weSyndicateNotesToMastodon(): void public function weSyndicateNotesToMastodon(): void
{ {
config(['bridgy.mastodon_token' => 'test']); config(['bridgy.mastodon_token' => 'test']);
@ -38,7 +39,7 @@ class SyndicateNoteToMastodonJobTest extends TestCase
]); ]);
} }
/** @test */ #[Test]
public function weSyndicateTheOriginalMarkdown(): void public function weSyndicateTheOriginalMarkdown(): void
{ {
config(['bridgy.mastodon_token' => 'test']); config(['bridgy.mastodon_token' => 'test']);

View file

@ -6,13 +6,14 @@ namespace Tests\Unit;
use App\Models\Like; use App\Models\Like;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class LikesTest extends TestCase class LikesTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
/** @test */ #[Test]
public function weCanSetTheAuthorUrl(): void public function weCanSetTheAuthorUrl(): void
{ {
$like = new Like; $like = new Like;
@ -20,7 +21,7 @@ class LikesTest extends TestCase
$this->assertEquals('https://joe.bloggs', $like->author_url); $this->assertEquals('https://joe.bloggs', $like->author_url);
} }
/** @test */ #[Test]
public function weDoNotModifyPlainTextContent(): void public function weDoNotModifyPlainTextContent(): void
{ {
$like = new Like; $like = new Like;
@ -31,7 +32,7 @@ class LikesTest extends TestCase
$this->assertEquals('some plaintext content', $like->content); $this->assertEquals('some plaintext content', $like->content);
} }
/** @test */ #[Test]
public function weCanHandleBlankContent(): void public function weCanHandleBlankContent(): void
{ {
$like = new Like; $like = new Like;
@ -42,7 +43,7 @@ class LikesTest extends TestCase
$this->assertNull($like->content); $this->assertNull($like->content);
} }
/** @test */ #[Test]
public function htmlLikeContentIsFiltered(): void public function htmlLikeContentIsFiltered(): void
{ {
$htmlEvil = <<<'HTML' $htmlEvil = <<<'HTML'

View file

@ -7,13 +7,14 @@ namespace Tests\Unit;
use App\Models\Media; use App\Models\Media;
use App\Models\Note; use App\Models\Note;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class MediaTest extends TestCase class MediaTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
/** @test */ #[Test]
public function getTheNoteThatMediaInstanceBelongsTo(): void public function getTheNoteThatMediaInstanceBelongsTo(): void
{ {
$media = Media::factory()->for(Note::factory())->create(); $media = Media::factory()->for(Note::factory())->create();
@ -21,7 +22,7 @@ class MediaTest extends TestCase
$this->assertInstanceOf(Note::class, $media->note); $this->assertInstanceOf(Note::class, $media->note);
} }
/** @test */ #[Test]
public function absoluteUrlsAreReturnedUnmodified(): void public function absoluteUrlsAreReturnedUnmodified(): void
{ {
$absoluteUrl = 'https://instagram-cdn.com/image/uuid'; $absoluteUrl = 'https://instagram-cdn.com/image/uuid';

View file

@ -7,13 +7,14 @@ namespace Tests\Unit;
use App\Models\MicropubClient; use App\Models\MicropubClient;
use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Collection;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class MicropubClientsTest extends TestCase class MicropubClientsTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
/** @test */ #[Test]
public function weCanGetNotesRelatingToClient(): void public function weCanGetNotesRelatingToClient(): void
{ {
$client = MicropubClient::factory()->make(); $client = MicropubClient::factory()->make();

View file

@ -16,6 +16,7 @@ use GuzzleHttp\Psr7\Response;
use Illuminate\Filesystem\Filesystem; use Illuminate\Filesystem\Filesystem;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class NotesTest extends TestCase class NotesTest extends TestCase
@ -25,9 +26,8 @@ class NotesTest extends TestCase
/** /**
* Test the getNoteAttribute method. This will then also call the * Test the getNoteAttribute method. This will then also call the
* relevant sub-methods. * relevant sub-methods.
*
* @test
*/ */
#[Test]
public function getNoteAttributeMethodCallsSubMethods(): void public function getNoteAttributeMethodCallsSubMethods(): void
{ {
// phpcs:ignore // phpcs:ignore
@ -40,9 +40,8 @@ class NotesTest extends TestCase
/** /**
* Look for a default image in the contacts h-card for the makeHCards method. * Look for a default image in the contacts h-card for the makeHCards method.
*
* @test
*/ */
#[Test]
public function defaultImageUsedAsFallbackInMakehcardsMethod(): void public function defaultImageUsedAsFallbackInMakehcardsMethod(): void
{ {
// phpcs:ignore // phpcs:ignore
@ -70,9 +69,8 @@ class NotesTest extends TestCase
/** /**
* Look for a specific profile image in the contacts h-card. * Look for a specific profile image in the contacts h-card.
*
* @test
*/ */
#[Test]
public function specificProfileImageUsedInMakehcardsMethod(): void public function specificProfileImageUsedInMakehcardsMethod(): void
{ {
Contact::factory()->create([ Contact::factory()->create([
@ -106,9 +104,8 @@ class NotesTest extends TestCase
/** /**
* Look for twitter URL when theres no associated contact. * Look for twitter URL when theres no associated contact.
*
* @test
*/ */
#[Test]
public function twitterLinkIsCreatedWhenNoContactFound(): void public function twitterLinkIsCreatedWhenNoContactFound(): void
{ {
$expected = '<p>Hi <a href="https://twitter.com/bob">@bob</a></p>' . PHP_EOL; $expected = '<p>Hi <a href="https://twitter.com/bob">@bob</a></p>' . PHP_EOL;
@ -118,7 +115,7 @@ class NotesTest extends TestCase
$this->assertEquals($expected, $note->note); $this->assertEquals($expected, $note->note);
} }
/** @test */ #[Test]
public function shorturlMethodReturnsExpectedValue(): void public function shorturlMethodReturnsExpectedValue(): void
{ {
$note = Note::factory()->make(); $note = Note::factory()->make();
@ -126,7 +123,7 @@ class NotesTest extends TestCase
$this->assertEquals(config('url.shorturl') . '/notes/E', $note->shorturl); $this->assertEquals(config('url.shorturl') . '/notes/E', $note->shorturl);
} }
/** @test */ #[Test]
public function weGetLatitudeLongitudeValuesOfAssociatedPlaceOfNote(): void public function weGetLatitudeLongitudeValuesOfAssociatedPlaceOfNote(): void
{ {
$place = Place::factory()->create([ $place = Place::factory()->create([
@ -140,7 +137,7 @@ class NotesTest extends TestCase
$this->assertEquals('-2.3805', $note->longitude); $this->assertEquals('-2.3805', $note->longitude);
} }
/** @test */ #[Test]
public function whenNoAssociatedPlaceWeGetNullForLatitudeLongitudeValues(): void public function whenNoAssociatedPlaceWeGetNullForLatitudeLongitudeValues(): void
{ {
$note = Note::factory()->create(); $note = Note::factory()->create();
@ -148,7 +145,7 @@ class NotesTest extends TestCase
$this->assertNull($note->longitude); $this->assertNull($note->longitude);
} }
/** @test */ #[Test]
public function weCanGetAddressAttributeForAssociatedPlace(): void public function weCanGetAddressAttributeForAssociatedPlace(): void
{ {
$place = Place::factory()->create([ $place = Place::factory()->create([
@ -162,7 +159,7 @@ class NotesTest extends TestCase
$this->assertEquals('The Bridgewater Pub', $note->address); $this->assertEquals('The Bridgewater Pub', $note->address);
} }
/** @test */ #[Test]
public function deletingNotesAlsoDeletesTagsViaTheEventObserver(): void public function deletingNotesAlsoDeletesTagsViaTheEventObserver(): void
{ {
// first well create a temporary note to delete // first well create a temporary note to delete
@ -177,7 +174,7 @@ class NotesTest extends TestCase
]); ]);
} }
/** @test */ #[Test]
public function saveBlankNotesAsNull(): void public function saveBlankNotesAsNull(): void
{ {
$note = new Note(['note' => '']); $note = new Note(['note' => '']);
@ -185,7 +182,7 @@ class NotesTest extends TestCase
$this->assertNull($note->note); $this->assertNull($note->note);
} }
/** @test */ #[Test]
public function reverseGeocodeAnAttraction(): void public function reverseGeocodeAnAttraction(): void
{ {
// phpcs:disable Generic.Files.LineLength.TooLong // phpcs:disable Generic.Files.LineLength.TooLong
@ -210,7 +207,7 @@ class NotesTest extends TestCase
); );
} }
/** @test */ #[Test]
public function reverseGeocodeASuburb(): void public function reverseGeocodeASuburb(): void
{ {
// phpcs:disable Generic.Files.LineLength.TooLong // phpcs:disable Generic.Files.LineLength.TooLong
@ -235,7 +232,7 @@ class NotesTest extends TestCase
); );
} }
/** @test */ #[Test]
public function reverseGeocodeACity(): void public function reverseGeocodeACity(): void
{ {
// Note Ive modified this JSON response so it only contains the // Note Ive modified this JSON response so it only contains the
@ -262,7 +259,7 @@ class NotesTest extends TestCase
); );
} }
/** @test */ #[Test]
public function reverseGeocodeACounty(): void public function reverseGeocodeACounty(): void
{ {
// Note Ive removed everything below county to test for queries where // Note Ive removed everything below county to test for queries where
@ -286,7 +283,7 @@ class NotesTest extends TestCase
$this->assertEquals('<span class="p-region">Kent</span>, <span class="p-country-name">UK</span>', $address); $this->assertEquals('<span class="p-region">Kent</span>, <span class="p-country-name">UK</span>', $address);
} }
/** @test */ #[Test]
public function reverseGeocodeACountry(): void public function reverseGeocodeACountry(): void
{ {
// Note Ive removed everything below country to test for querires where // Note Ive removed everything below country to test for querires where
@ -310,7 +307,7 @@ class NotesTest extends TestCase
$this->assertEquals('<span class="p-country-name">Ireland</span>', $address); $this->assertEquals('<span class="p-country-name">Ireland</span>', $address);
} }
/** @test */ #[Test]
public function addImageElementToNoteContentWhenMediaAssociated(): void public function addImageElementToNoteContentWhenMediaAssociated(): void
{ {
$media = Media::factory()->create([ $media = Media::factory()->create([
@ -327,7 +324,7 @@ class NotesTest extends TestCase
$this->assertEquals($expected, $note->content); $this->assertEquals($expected, $note->content);
} }
/** @test */ #[Test]
public function addVideoElementToNoteContentWhenMediaAssociated(): void public function addVideoElementToNoteContentWhenMediaAssociated(): void
{ {
$media = Media::factory()->create([ $media = Media::factory()->create([
@ -344,7 +341,7 @@ class NotesTest extends TestCase
$this->assertEquals($expected, $note->content); $this->assertEquals($expected, $note->content);
} }
/** @test */ #[Test]
public function addAudioElementToNoteContentWhenMediaAssociated(): void public function addAudioElementToNoteContentWhenMediaAssociated(): void
{ {
$media = Media::factory()->create([ $media = Media::factory()->create([
@ -362,10 +359,9 @@ class NotesTest extends TestCase
} }
/** /**
* @test
*
* @todo Why do we need to provide text? * @todo Why do we need to provide text?
*/ */
#[Test]
public function provideTextForBlankContent(): void public function provideTextForBlankContent(): void
{ {
$note = new Note; $note = new Note;
@ -382,9 +378,8 @@ class NotesTest extends TestCase
$this->assertNull($note->twitter); $this->assertNull($note->twitter);
}*/ }*/
#[Test]
/** @test */ public function markdown_content_gets_converted(): void
public function markdownContentGetsConverted(): void
{ {
$note = Note::factory()->create([ $note = Note::factory()->create([
'note' => 'The best search engine? https://duckduckgo.com', 'note' => 'The best search engine? https://duckduckgo.com',
@ -398,9 +393,8 @@ class NotesTest extends TestCase
/** /**
* For now, just reply on a cached object instead of actually querying Twitter. * For now, just reply on a cached object instead of actually querying Twitter.
*
* @test
*/ */
#[Test]
public function checkInReplyToIsTwitterLink(): void public function checkInReplyToIsTwitterLink(): void
{ {
$tempContent = (object) [ $tempContent = (object) [
@ -415,7 +409,7 @@ class NotesTest extends TestCase
$this->assertEquals($tempContent, $note->twitter); $this->assertEquals($tempContent, $note->twitter);
} }
/** @test */ #[Test]
public function latitudeAndLongitudeCanBeParsedFromPlainLocation(): void public function latitudeAndLongitudeCanBeParsedFromPlainLocation(): void
{ {
$note = Note::factory()->create([ $note = Note::factory()->create([
@ -426,7 +420,7 @@ class NotesTest extends TestCase
$this->assertSame(4.56, $note->longitude); $this->assertSame(4.56, $note->longitude);
} }
/** @test */ #[Test]
public function addressAttributeCanBeRetrievedFromPlainLocation(): void public function addressAttributeCanBeRetrievedFromPlainLocation(): void
{ {
Cache::put('1.23,4.56', '<span class="p-country-name">Antarctica</span>'); Cache::put('1.23,4.56', '<span class="p-country-name">Antarctica</span>');
@ -438,7 +432,7 @@ class NotesTest extends TestCase
$this->assertSame('<span class="p-country-name">Antarctica</span>', $note->address); $this->assertSame('<span class="p-country-name">Antarctica</span>', $note->address);
} }
/** @test */ #[Test]
public function mastodonUsernamesAreParsedCorrectly(): void public function mastodonUsernamesAreParsedCorrectly(): void
{ {
$expected = '<p>Hi <a href="https://phpc.social/@freekmurze">@freekmurze@phpc.social</a> how are you?</p>' . PHP_EOL; $expected = '<p>Hi <a href="https://phpc.social/@freekmurze">@freekmurze@phpc.social</a> how are you?</p>' . PHP_EOL;

View file

@ -10,13 +10,14 @@ use App\Services\PlaceService;
use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Collection;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use InvalidArgumentException; use InvalidArgumentException;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class PlacesTest extends TestCase class PlacesTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
/** @test */ #[Test]
public function canRetrieveAssociatedNotes(): void public function canRetrieveAssociatedNotes(): void
{ {
$place = Place::factory()->create(); $place = Place::factory()->create();
@ -27,7 +28,7 @@ class PlacesTest extends TestCase
$this->assertCount(5, $place->notes); $this->assertCount(5, $place->notes);
} }
/** @test */ #[Test]
public function nearMethodReturnsCollection(): void public function nearMethodReturnsCollection(): void
{ {
Place::factory()->create([ Place::factory()->create([
@ -39,7 +40,7 @@ class PlacesTest extends TestCase
$this->assertEquals('the-bridgewater-pub', $nearby[0]->slug); $this->assertEquals('the-bridgewater-pub', $nearby[0]->slug);
} }
/** @test */ #[Test]
public function getLongurl(): void public function getLongurl(): void
{ {
$place = Place::factory()->create([ $place = Place::factory()->create([
@ -48,7 +49,7 @@ class PlacesTest extends TestCase
$this->assertEquals(config('app.url') . '/places/the-bridgewater-pub', $place->longurl); $this->assertEquals(config('app.url') . '/places/the-bridgewater-pub', $place->longurl);
} }
/** @test */ #[Test]
public function getShorturl() public function getShorturl()
{ {
$place = Place::factory()->create([ $place = Place::factory()->create([
@ -57,7 +58,7 @@ class PlacesTest extends TestCase
$this->assertEquals(config('url.shorturl') . '/places/the-bridgewater-pub', $place->shorturl); $this->assertEquals(config('url.shorturl') . '/places/the-bridgewater-pub', $place->shorturl);
} }
/** @test */ #[Test]
public function getUri(): void public function getUri(): void
{ {
$place = Place::factory()->create([ $place = Place::factory()->create([
@ -66,7 +67,7 @@ class PlacesTest extends TestCase
$this->assertEquals(config('app.url') . '/places/the-bridgewater-pub', $place->uri); $this->assertEquals(config('app.url') . '/places/the-bridgewater-pub', $place->uri);
} }
/** @test */ #[Test]
public function placeServiceReturnsExistingPlaceBasedOnExternalUrlsSearch(): void public function placeServiceReturnsExistingPlaceBasedOnExternalUrlsSearch(): void
{ {
Place::factory(10)->create(); Place::factory(10)->create();
@ -86,7 +87,7 @@ class PlacesTest extends TestCase
$this->assertCount(11, Place::all()); $this->assertCount(11, Place::all());
} }
/** @test */ #[Test]
public function placeServiceRequiresNameWhenCreatingNewPlace(): void public function placeServiceRequiresNameWhenCreatingNewPlace(): void
{ {
$this->expectException(InvalidArgumentException::class); $this->expectException(InvalidArgumentException::class);
@ -96,7 +97,7 @@ class PlacesTest extends TestCase
$service->createPlaceFromCheckin(['foo' => 'bar']); $service->createPlaceFromCheckin(['foo' => 'bar']);
} }
/** @test */ #[Test]
public function placeServiceRequiresLatitudeWhenCreatingNewPlace(): void public function placeServiceRequiresLatitudeWhenCreatingNewPlace(): void
{ {
$this->expectException(InvalidArgumentException::class); $this->expectException(InvalidArgumentException::class);
@ -106,7 +107,7 @@ class PlacesTest extends TestCase
$service->createPlaceFromCheckin(['properties' => ['name' => 'bar']]); $service->createPlaceFromCheckin(['properties' => ['name' => 'bar']]);
} }
/** @test */ #[Test]
public function placeServiceCanUpdateExternalUrls(): void public function placeServiceCanUpdateExternalUrls(): void
{ {
$place = Place::factory()->create([ $place = Place::factory()->create([

View file

@ -8,13 +8,15 @@ use App\Models\Bookmark;
use App\Models\Note; use App\Models\Note;
use App\Models\Tag; use App\Models\Tag;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase; use Tests\TestCase;
class TagsTest extends TestCase class TagsTest extends TestCase
{ {
use RefreshDatabase; use RefreshDatabase;
/** @test */ #[Test]
public function canGetAssociatedNotes(): void public function canGetAssociatedNotes(): void
{ {
$note = Note::factory()->create(); $note = Note::factory()->create();
@ -23,7 +25,7 @@ class TagsTest extends TestCase
$this->assertCount(1, $tag->notes); $this->assertCount(1, $tag->notes);
} }
/** @test */ #[Test]
public function canGetAssociatedBookmarks(): void public function canGetAssociatedBookmarks(): void
{ {
$bookmark = Bookmark::factory()->create(); $bookmark = Bookmark::factory()->create();
@ -32,11 +34,8 @@ class TagsTest extends TestCase
$this->assertCount(1, $tag->bookmarks); $this->assertCount(1, $tag->bookmarks);
} }
/** #[Test]
* @test #[DataProvider('tagsProvider')]
*
* @dataProvider tagsProvider
*/
public function canNormalize(string $input, string $expected): void public function canNormalize(string $input, string $expected): void
{ {
$this->assertSame($expected, Tag::normalize($input)); $this->assertSame($expected, Tag::normalize($input));

Some files were not shown because too many files have changed in this diff Show more