feat: 前台 .shtml 后缀 canonical + strict_types 全量启用 + 对外 API(Sanctum+Scramble 文档)+ pm2 ecosystem + GitHub Actions CI + 插件/主题/架构/API 文档 + REDIS_PREFIX 说明
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\Category;
|
||||
use App\Models\Post;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ApiTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->seed();
|
||||
|
||||
$user = User::create(['name' => '作者', 'email' => 'w@t.com', 'password' => bcrypt('x')]);
|
||||
$cat = Category::create(['name' => '技术', 'slug' => 'tech']);
|
||||
Post::create([
|
||||
'user_id' => $user->id,
|
||||
'category_id' => $cat->id,
|
||||
'title' => 'API 测试文章',
|
||||
'slug' => 'api-post',
|
||||
'content' => '**加粗** 内容',
|
||||
'content_format' => 'markdown',
|
||||
'status' => 'published',
|
||||
'published_at' => now(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_site_endpoint(): void
|
||||
{
|
||||
$this->getJson('/api/site')->assertOk()->assertJsonPath('api_version', '1.0');
|
||||
}
|
||||
|
||||
public function test_posts_list_and_detail(): void
|
||||
{
|
||||
$this->getJson('/api/posts')->assertOk()->assertJsonCount(1, 'data');
|
||||
$this->getJson('/api/posts/api-post')
|
||||
->assertOk()
|
||||
->assertJsonPath('title', 'API 测试文章')
|
||||
->assertJsonPath('category.name', '技术');
|
||||
}
|
||||
|
||||
public function test_posts_search_and_filters(): void
|
||||
{
|
||||
$this->getJson('/api/posts?q=API')->assertOk()->assertJsonCount(1, 'data');
|
||||
$this->getJson('/api/posts?category=tech')->assertOk()->assertJsonCount(1, 'data');
|
||||
$this->getJson('/api/posts?q=不存在的词')->assertOk()->assertJsonCount(0, 'data');
|
||||
}
|
||||
|
||||
public function test_categories_and_tags(): void
|
||||
{
|
||||
$this->getJson('/api/categories')->assertOk()->assertJsonCount(1, 'data');
|
||||
$this->getJson('/api/tags')->assertOk();
|
||||
}
|
||||
|
||||
public function test_store_comment(): void
|
||||
{
|
||||
$post = Post::where('slug', 'api-post')->first();
|
||||
|
||||
$this->postJson('/api/comments', [
|
||||
'post_id' => $post->id,
|
||||
'author_name' => 'API 访客',
|
||||
'content' => '来自 API 的评论',
|
||||
'website' => '',
|
||||
])->assertCreated()->assertJsonPath('data.status', 'published');
|
||||
|
||||
$this->assertDatabaseHas('comments', ['author_name' => 'API 访客']);
|
||||
}
|
||||
|
||||
public function test_comment_honeypot_rejected(): void
|
||||
{
|
||||
$post = Post::where('slug', 'api-post')->first();
|
||||
|
||||
$this->postJson('/api/comments', [
|
||||
'post_id' => $post->id,
|
||||
'author_name' => '机器人',
|
||||
'content' => 'spam',
|
||||
'website' => 'http://spam.example.com',
|
||||
])->assertStatus(422);
|
||||
}
|
||||
|
||||
public function test_me_requires_token(): void
|
||||
{
|
||||
$this->getJson('/api/me')->assertUnauthorized();
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ class ExampleTest extends TestCase
|
||||
$this->seed();
|
||||
|
||||
$this->get('/')->assertStatus(200);
|
||||
$this->get('/archives')->assertStatus(200);
|
||||
$this->get('/archives.shtml')->assertStatus(200);
|
||||
$this->get('/rss.xml')->assertStatus(200);
|
||||
$this->get('/sitemap.xml')->assertStatus(200);
|
||||
$this->get('/robots.txt')->assertStatus(200);
|
||||
|
||||
@@ -41,25 +41,43 @@ class LegacyRoutesTest extends TestCase
|
||||
|
||||
public function test_rewrite_style_urls_redirect(): void
|
||||
{
|
||||
$this->get('/show-12.html')->assertRedirect('/posts/legacy-post');
|
||||
$this->get('/show-12-1.html')->assertRedirect('/posts/legacy-post');
|
||||
$this->get('/show-12.html')->assertRedirect('/posts/legacy-post.shtml');
|
||||
$this->get('/show-12-1.html')->assertRedirect('/posts/legacy-post.shtml');
|
||||
$this->get('/category-1.html')->assertRedirect();
|
||||
$this->get('/archives-'.now()->format('Ymd').'.html')->assertRedirect();
|
||||
$this->get('/tagslist.html')->assertRedirect('/tags');
|
||||
$this->get('/links.shtml')->assertRedirect('/links');
|
||||
$this->get('/login.shtml')->assertRedirect('/login');
|
||||
$this->get('/reg.shtml')->assertRedirect('/register');
|
||||
$this->get('/tagslist.html')->assertRedirect('/tags.shtml');
|
||||
$this->get('/reg.shtml')->assertRedirect('/register.shtml');
|
||||
}
|
||||
|
||||
public function test_shtml_canonical_pages_render(): void
|
||||
{
|
||||
$this->get('/links.shtml')->assertOk();
|
||||
$this->get('/login.shtml')->assertOk();
|
||||
$this->get('/comments.shtml')->assertOk();
|
||||
$this->get('/search.shtml')->assertOk();
|
||||
$this->get('/tags.shtml')->assertOk();
|
||||
$this->get('/archives.shtml')->assertOk();
|
||||
$this->get('/posts/legacy-post.shtml')->assertOk();
|
||||
}
|
||||
|
||||
public function test_no_suffix_urls_redirect_to_shtml(): void
|
||||
{
|
||||
$this->get('/links')->assertRedirect('/links.shtml');
|
||||
$this->get('/login')->assertRedirect('/login.shtml');
|
||||
$this->get('/comments')->assertRedirect('/comments.shtml');
|
||||
$this->get('/archives')->assertRedirect('/archives.shtml');
|
||||
$this->get('/posts/legacy-post')->assertRedirect('/posts/legacy-post.shtml');
|
||||
}
|
||||
|
||||
public function test_query_style_urls_redirect(): void
|
||||
{
|
||||
$this->get('/?action=show&id=12')->assertRedirect('/posts/legacy-post');
|
||||
$this->get('/?action=show&id=12')->assertRedirect('/posts/legacy-post.shtml');
|
||||
$this->get('/?action=category&cid=1')->assertRedirect();
|
||||
$this->get('/?action=index&setdate='.now()->format('Ym'))->assertRedirect();
|
||||
$this->get('/?action=search&keyword=laravel')->assertRedirect('/search?q=laravel');
|
||||
$this->get('/?action=links')->assertRedirect('/links');
|
||||
$this->get('/?action=archives')->assertRedirect('/archives');
|
||||
$this->get('/?action=comments')->assertRedirect('/comments');
|
||||
$this->get('/?action=search&keyword=laravel')->assertRedirect('/search.shtml?q=laravel');
|
||||
$this->get('/?action=links')->assertRedirect('/links.shtml');
|
||||
$this->get('/?action=archives')->assertRedirect('/archives.shtml');
|
||||
$this->get('/?action=comments')->assertRedirect('/comments.shtml');
|
||||
}
|
||||
|
||||
public function test_trackback_endpoints_are_gone(): void
|
||||
@@ -86,6 +104,6 @@ class LegacyRoutesTest extends TestCase
|
||||
$tag = Tag::create(['name' => 'laravel-tag', 'type' => 'post']);
|
||||
Setting::set('legacy_tags', [1 => $tag->id]);
|
||||
|
||||
$this->get('/?action=tags&id=1')->assertRedirect('/tags/laravel-tag');
|
||||
$this->get('/?action=tags&id=1')->assertRedirect('/tags/laravel-tag.shtml');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ class MembershipFlowTest extends TestCase
|
||||
]);
|
||||
|
||||
// 游客:付费部分被替换
|
||||
$this->get('/posts/paid-post')
|
||||
$this->get('/posts/paid-post.shtml')
|
||||
->assertOk()
|
||||
->assertDontSee('付费隐藏内容')
|
||||
->assertSee('付费内容已隐藏');
|
||||
@@ -97,7 +97,7 @@ class MembershipFlowTest extends TestCase
|
||||
$payment = Payment::query()->where('user_id', $this->user->id)->first();
|
||||
$this->actingAs($this->user)->post('/pay/sandbox/'.$payment->order_no.'/confirm');
|
||||
|
||||
$this->actingAs($this->user)->get('/posts/paid-post')
|
||||
$this->actingAs($this->user)->get('/posts/paid-post.shtml')
|
||||
->assertOk()
|
||||
->assertSee('付费隐藏内容');
|
||||
}
|
||||
|
||||
@@ -37,14 +37,14 @@ class ThemeTest extends TestCase
|
||||
{
|
||||
app(\App\Blog\Support\ThemeManager::class)->activate('sablog');
|
||||
$this->get('/')->assertOk()->assertSee('outmain');
|
||||
$this->get('/posts/theme-test')->assertOk()->assertSee('outmain');
|
||||
$this->get('/posts/theme-test.shtml')->assertOk()->assertSee('outmain');
|
||||
}
|
||||
|
||||
public function test_modern_theme_renders_modern_layout(): void
|
||||
{
|
||||
app(\App\Blog\Support\ThemeManager::class)->activate('modern');
|
||||
$this->get('/')->assertOk()->assertSee('m-header');
|
||||
$this->get('/posts/theme-test')->assertOk()->assertSee('m-header');
|
||||
$this->get('/posts/theme-test.shtml')->assertOk()->assertSee('m-header');
|
||||
}
|
||||
|
||||
public function test_theme_assets_are_served(): void
|
||||
|
||||
Reference in New Issue
Block a user