Finish re-working tests to run on test database

This commit is contained in:
Jonny Barnes 2021-08-31 12:28:00 +01:00
commit 1abca77bdc
50 changed files with 535 additions and 265 deletions

View file

@ -7,7 +7,7 @@ APP_LOG_LEVEL=warning
DB_CONNECTION=pgsql DB_CONNECTION=pgsql
DB_HOST=127.0.0.1 DB_HOST=127.0.0.1
DB_PORT=5432 DB_PORT=5432
DB_DATABASE=jbuktest DB_DATABASE=jbukdev_testing
DB_USERNAME=postgres DB_USERNAME=postgres
DB_PASSWORD=postgres DB_PASSWORD=postgres

View file

@ -1,17 +0,0 @@
APP_ENV=testing
APP_DEBUG=true
APP_KEY=base64:6DJhvZLVjE6dD4Cqrteh+6Z5vZlG+v/soCKcDHLOAH0=
APP_URL=http://jonnybarnes.localhost
APP_LONGURL=jonnybarnes.localhost
APP_SHORTURL=jmb.localhost
DB_CONNECTION=travis
CACHE_DRIVER=array
SESSION_DRIVER=array
QUEUE_DRIVER=sync
SCOUT_DRIVER=pgsql
DISPLAY_NAME='Travis Test'
USER_NAME=travis

View file

@ -11,11 +11,11 @@ jobs:
services: services:
postgres: postgres:
image: postgres:13.1 image: postgres:13.2
env: env:
POSTGRES_USER: postgres POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres POSTGRES_PASSWORD: postgres
POSTGRES_DB: jbuktest POSTGRES_DB: jbukdev_testing
ports: ports:
- 5432:5432 - 5432:5432

View file

@ -24,16 +24,6 @@ class ParseCachedWebMentions extends Command
*/ */
protected $description = 'Re-parse the webmention’s cached HTML'; protected $description = 'Re-parse the webmention’s cached HTML';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/** /**
* Execute the console command. * Execute the console command.
* *
@ -41,15 +31,15 @@ class ParseCachedWebMentions extends Command
*/ */
public function handle(FileSystem $filesystem) public function handle(FileSystem $filesystem)
{ {
$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 don’t want to parse.backup files if ($file->getExtension() !== 'backup') { //we don’t 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);
$url = $this->URLFromFilename($filepath); $url = $this->urlFromFilename($filepath);
$microformats = \Mf2\parse($html, $url);
$webmention = WebMention::where('source', $url)->firstOrFail(); $webmention = WebMention::where('source', $url)->firstOrFail();
$microformats = \Mf2\parse($html, $url);
$webmention->mf2 = json_encode($microformats); $webmention->mf2 = json_encode($microformats);
$webmention->save(); $webmention->save();
$this->info('Saved the microformats to the database.'); $this->info('Saved the microformats to the database.');
@ -63,12 +53,12 @@ class ParseCachedWebMentions extends Command
* @param string * @param string
* @return string * @return string
*/ */
private function URLFromFilename(string $filepath): string private function urlFromFilename(string $filepath): string
{ {
$dir = mb_substr($filepath, mb_strlen(storage_path() . '/HTML/')); $dir = mb_substr($filepath, mb_strlen(storage_path() . '/HTML/'));
$url = str_replace(['http/', 'https/'], ['http://', 'https://'], $dir); $url = str_replace(['http/', 'https/'], ['http://', 'https://'], $dir);
if (mb_substr($url, -10) == 'index.html') { if (mb_substr($url, -10) === 'index.html') {
$url = mb_substr($url, 0, mb_strlen($url) - 10); $url = mb_substr($url, 0, -10);
} }
return $url; return $url;

View file

@ -7,16 +7,10 @@ namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\Article; use App\Models\Article;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View; use Illuminate\View\View;
class ArticlesController extends Controller class ArticlesController extends Controller
{ {
/**
* List the articles that can be edited.
*
* @return \Illuminate\View\View
*/
public function index(): View public function index(): View
{ {
$posts = Article::select('id', 'title', 'published')->orderBy('id', 'desc')->get(); $posts = Article::select('id', 'title', 'published')->orderBy('id', 'desc')->get();
@ -24,11 +18,6 @@ class ArticlesController extends Controller
return view('admin.articles.index', ['posts' => $posts]); return view('admin.articles.index', ['posts' => $posts]);
} }
/**
* Show the new article form.
*
* @return \Illuminate\View\View
*/
public function create(): View public function create(): View
{ {
$message = session('message'); $message = session('message');
@ -36,11 +25,6 @@ class ArticlesController extends Controller
return view('admin.articles.create', ['message' => $message]); return view('admin.articles.create', ['message' => $message]);
} }
/**
* Process an incoming request for a new article and save it.
*
* @return \Illuminate\Http\RedirectResponse
*/
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.
@ -49,42 +33,21 @@ class ArticlesController extends Controller
$content = $file->fread($file->getSize()); $content = $file->fread($file->getSize());
} }
$main = $content ?? request()->input('main'); $main = $content ?? request()->input('main');
$article = Article::create( Article::create([
[ 'url' => request()->input('url'),
'url' => request()->input('url'), 'title' => request()->input('title'),
'title' => request()->input('title'), 'main' => $main,
'main' => $main, 'published' => request()->input('published') ?? 0,
'published' => request()->input('published') ?? 0, ]);
]
);
return redirect('/admin/blog'); return redirect('/admin/blog');
} }
/** public function edit(Article $article): View
* Show the edit form for an existing article.
*
* @param int $articleId
* @return \Illuminate\View\View
*/
public function edit(int $articleId): View
{ {
$post = Article::select( return view('admin.articles.edit', ['article' => $article]);
'title',
'main',
'url',
'published'
)->where('id', $articleId)->get();
return view('admin.articles.edit', ['id' => $articleId, 'post' => $post]);
} }
/**
* Process an incoming request to edit an article.
*
* @param int $articleId
* @return \Illuminate\Http\RedirectResponse
*/
public function update(int $articleId): RedirectResponse public function update(int $articleId): RedirectResponse
{ {
$article = Article::find($articleId); $article = Article::find($articleId);
@ -97,12 +60,6 @@ class ArticlesController extends Controller
return redirect('/admin/blog'); return redirect('/admin/blog');
} }
/**
* Process a request to delete an aricle.
*
* @param int $articleId
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(int $articleId): RedirectResponse public function destroy(int $articleId): RedirectResponse
{ {
Article::where('id', $articleId)->delete(); Article::where('id', $articleId)->delete();

View file

@ -59,18 +59,14 @@ class ArticlesController extends Controller
* We only have the ID, work out post title, year and month * We only have the ID, work out post title, year and month
* and redirect to it. * and redirect to it.
* *
* @param int $idFromUrl * @param string $idFromUrl
* @return RedirectResponse * @return RedirectResponse
*/ */
public function onlyIdInUrl(int $idFromUrl): RedirectResponse public function onlyIdInUrl(string $idFromUrl): RedirectResponse
{ {
$realId = resolve(Numbers::class)->b60tonum((string) $idFromUrl); $realId = resolve(Numbers::class)->b60tonum($idFromUrl);
try { $article = Article::findOrFail($realId);
$article = Article::findOrFail($realId);
} catch (ModelNotFoundException $exception) {
abort(404);
}
return redirect($article->link); return redirect($article->link);
} }

View file

@ -7,6 +7,7 @@ namespace App\Models;
use Cviebrock\EloquentSluggable\Sluggable; use Cviebrock\EloquentSluggable\Sluggable;
use Eloquent; use Eloquent;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
@ -58,6 +59,7 @@ use Spatie\CommonMarkHighlighter\IndentedCodeRenderer;
*/ */
class Article extends Model class Article extends Model
{ {
use HasFactory;
use Sluggable; use Sluggable;
use SoftDeletes; use SoftDeletes;

View file

@ -6,6 +6,7 @@ namespace App\Models;
use Eloquent; use Eloquent;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
@ -35,6 +36,8 @@ use Illuminate\Support\Carbon;
*/ */
class Contact extends Model class Contact extends Model
{ {
use HasFactory;
/** /**
* The database table used by the model. * The database table used by the model.
* *

View file

@ -6,6 +6,7 @@ namespace App\Models;
use Eloquent; use Eloquent;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
@ -41,6 +42,8 @@ use Illuminate\Support\Str;
*/ */
class Media extends Model class Media extends Model
{ {
use HasFactory;
/** /**
* The table associated with the model. * The table associated with the model.
* *
@ -62,7 +65,7 @@ class Media extends Model
*/ */
public function note(): BelongsTo public function note(): BelongsTo
{ {
return $this->belongsTo('App\Models\Note'); return $this->belongsTo(Note::class);
} }
/** /**
@ -118,7 +121,7 @@ class Media extends Model
$filenameParts = explode('.', $path); $filenameParts = explode('.', $path);
array_pop($filenameParts); array_pop($filenameParts);
return ltrim(array_reduce($filenameParts, function ($carry, $item) { return ltrim(array_reduce($filenameParts, static function ($carry, $item) {
return $carry . '.' . $item; return $carry . '.' . $item;
}, ''), '.'); }, ''), '.');
} }

View file

@ -51,7 +51,7 @@ class Tag extends Model
*/ */
public function notes() public function notes()
{ {
return $this->belongsToMany('App\Models\Note'); return $this->belongsToMany(Note::class);
} }
/** /**

View file

@ -8,6 +8,7 @@ use App\Traits\FilterHtml;
use Codebird\Codebird; use Codebird\Codebird;
use Eloquent; use Eloquent;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Filesystem\Filesystem; use Illuminate\Filesystem\Filesystem;
@ -55,6 +56,7 @@ use Jonnybarnes\WebmentionsParser\Exceptions\AuthorshipParserException;
class WebMention extends Model class WebMention extends Model
{ {
use FilterHtml; use FilterHtml;
use HasFactory;
/** /**
* The database table used by the model. * The database table used by the model.

View file

@ -0,0 +1,34 @@
<?php
namespace Database\Factories;
use App\Models\Article;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Carbon;
class ArticleFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Article::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'titleurl' => $this->faker->slug(3),
'title' => $this->faker->words(3, true),
'main' => $this->faker->paragraphs(4, true),
'published' => 1,
'created_at' => Carbon::now()->toDateTimeString(),
'updated_at' => Carbon::now()->toDateTimeString(),
];
}
}

View file

@ -0,0 +1,35 @@
<?php
namespace Database\Factories;
use App\Models\Contact;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Carbon;
class ContactFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Contact::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'nick' => mb_strtolower($this->faker->firstName),
'name' => $this->faker->name(),
'homepage' => $this->faker->url,
'twitter' => mb_strtolower($this->faker->firstName),
'facebook' => $this->faker->randomNumber(5),
'created_at' => Carbon::now()->toDateTimeString(),
'updated_at' => Carbon::now()->toDateTimeString(),
];
}
}

View file

@ -0,0 +1,32 @@
<?php
namespace Database\Factories;
use App\Models\Media;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Carbon;
class MediaFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Media::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'path' => 'media/' . $this->faker->uuid . '.jpg',
'type' => 'image',
'created_at' => Carbon::now()->toDateTimeString(),
'updated_at' => Carbon::now()->toDateTimeString(),
];
}
}

View file

@ -3,6 +3,7 @@
namespace Database\Factories; namespace Database\Factories;
use App\Models\Note; use App\Models\Note;
use Exception;
use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
@ -19,10 +20,11 @@ class NoteFactory extends Factory
* Define the model's default state. * Define the model's default state.
* *
* @return array * @return array
* @throws Exception
*/ */
public function definition() public function definition()
{ {
$now = Carbon::now()->subDays(rand(5, 15)); $now = Carbon::now()->subDays(random_int(5, 15));
return [ return [
'note' => $this->faker->paragraph, 'note' => $this->faker->paragraph,

View file

@ -0,0 +1,31 @@
<?php
namespace Database\Factories;
use App\Models\WebMention;
use Illuminate\Database\Eloquent\Factories\Factory;
class WebMentionFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = WebMention::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'source' => $this->faker->url,
'target' => url('notes/1'),
'type' => 'reply',
'content' => $this->faker->paragraph,
];
}
}

View file

@ -16,6 +16,7 @@
</testsuites> </testsuites>
<php> <php>
<env name="APP_ENV" value="testing"/> <env name="APP_ENV" value="testing"/>
<env name="DB_DATABASE" value="jbukdev_testing"/>
<env name="BCRYPT_ROUNDS" value="4"/> <env name="BCRYPT_ROUNDS" value="4"/>
<env name="CACHE_DRIVER" value="array"/> <env name="CACHE_DRIVER" value="array"/>
<env name="MAIL_DRIVER" value="array"/> <env name="MAIL_DRIVER" value="array"/>

View file

@ -3,28 +3,28 @@
@section('title')Edit Article « Admin CP « @stop @section('title')Edit Article « Admin CP « @stop
@section('content') @section('content')
<form action="/admin/blog/{{ $id }}" method="post" accept-charset="utf-8" class="admin-form form"> <form action="/admin/blog/{{ $article->id }}" method="post" accept-charset="utf-8" class="admin-form form">
{{ csrf_field() }} {{ csrf_field() }}
{{ method_field('PUT') }} {{ method_field('PUT') }}
<div> <div>
<label for="title">Title (URL):</label> <label for="title">Title (URL):</label>
<input type="text" name="title" id="title" value="{!! $post['0']['title'] !!}"> <input type="text" name="title" id="title" value="{!! $article->title !!}">
<input type="url" name="url" id="url" value="{!! $post['0']['url'] !!}"> <input type="url" name="url" id="url" value="{!! $article->url !!}">
</div> </div>
<div> <div>
<label for="main">Main:</label> <label for="main">Main:</label>
<textarea name="main" id="main">{{ $post['0']['main'] }}</textarea> <textarea name="main" id="main">{!! $article->main !!}</textarea>
</div> </div>
<div class="form-row"> <div class="form-row">
<label for="published">Published:</label> <label for="published">Published:</label>
<input type="checkbox" name="published" value="1"@if($post['0']['published'] == '1') checked="checked"@endif> <input type="checkbox" name="published" value="1"@if($article->published == '1') checked="checked"@endif>
</div> </div>
<div> <div>
<button type="submit" name="save">Save</button> <button type="submit" name="save">Save</button>
</div> </div>
</form> </form>
<hr> <hr>
<form action="/admin/blog/{{ $id }}" method="post" class="admin-form form"> <form action="/admin/blog/{{ $article->id }}" method="post" class="admin-form form">
{{ csrf_field() }} {{ csrf_field() }}
{{ method_field('DELETE') }} {{ method_field('DELETE') }}
<div> <div>

View file

@ -65,7 +65,7 @@ Route::group(['domain' => config('url.longurl')], function () {
Route::get('/', [AdminArticlesController::class, 'index']); Route::get('/', [AdminArticlesController::class, 'index']);
Route::get('/create', [AdminArticlesController::class, 'create']); Route::get('/create', [AdminArticlesController::class, 'create']);
Route::post('/', [AdminArticlesController::class, 'store']); Route::post('/', [AdminArticlesController::class, 'store']);
Route::get('/{id}/edit', [AdminArticlesController::class, 'edit']); Route::get('/{article}/edit', [AdminArticlesController::class, 'edit']);
Route::put('/{id}', [AdminArticlesController::class, 'update']); Route::put('/{id}', [AdminArticlesController::class, 'update']);
Route::delete('/{id}', [AdminArticlesController::class, 'destroy']); Route::delete('/{id}', [AdminArticlesController::class, 'destroy']);
}); });

View file

@ -25,8 +25,8 @@ class ActivityStreamTest extends TestCase
/** @test */ /** @test */
public function requestForNoteIncludesActivityStreamData(): void public function requestForNoteIncludesActivityStreamData(): void
{ {
$note = Note::find(11); $note = Note::factory()->create();
$response = $this->get('/notes/B', ['Accept' => 'application/activity+json']); $response = $this->get($note->longurl, ['Accept' => 'application/activity+json']);
$response->assertHeader('Content-Type', 'application/activity+json'); $response->assertHeader('Content-Type', 'application/activity+json');
$response->assertJson([ $response->assertJson([
'@context' => 'https://www.w3.org/ns/activitystreams', '@context' => 'https://www.w3.org/ns/activitystreams',

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