|
|
@@ -78,12 +78,12 @@ class AnnouncementTest extends TestCase
|
|
|
public function test_websocket_events_cover_publication_boundaries_cancel_old_schedules_and_roll_back(): void
|
|
|
{
|
|
|
$row = $this->create(['publish_immediately' => false, 'publish_at' => '2026-10-26 11:00:00', 'no_end' => false, 'end_at' => '2026-10-26 12:00:00']);
|
|
|
- $this->assertSame(['create', 'start', 'end'], DB::table('site_realtime_events')->orderBy('id')->pluck('action')->all());
|
|
|
- $this->assertSame(['2026-10-26 10:00:00', '2026-10-26 11:00:00', '2026-10-26 12:00:00'], DB::table('site_realtime_events')->orderBy('id')->pluck('available_at')->all());
|
|
|
+ $this->assertSame(['start', 'end'], DB::table('site_realtime_events')->orderBy('id')->pluck('action')->all());
|
|
|
+ $this->assertSame(['2026-10-26 11:00:00', '2026-10-26 12:00:00'], DB::table('site_realtime_events')->orderBy('id')->pluck('available_at')->all());
|
|
|
$this->service->status($row['id'], 0); $this->service->status($row['id'], 0);
|
|
|
- $this->assertSame(['create', 'status'], DB::table('site_realtime_events')->orderBy('id')->pluck('action')->all());
|
|
|
+ $this->assertSame([], DB::table('site_realtime_events')->orderBy('id')->pluck('action')->all());
|
|
|
DB::beginTransaction(); $this->create(); DB::rollBack();
|
|
|
- $this->assertSame(2, DB::table('site_realtime_events')->count());
|
|
|
+ $this->assertSame(0, DB::table('site_realtime_events')->count());
|
|
|
}
|
|
|
|
|
|
private function create(array $params = []): array
|
|
|
@@ -283,6 +283,48 @@ class AnnouncementTest extends TestCase
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ public function test_delete_removes_announcement_and_translations_and_cancels_notifications(): void
|
|
|
+ {
|
|
|
+ $row = $this->create(['publish_immediately' => false, 'publish_at' => '2026-10-26 11:00:00']);
|
|
|
+ $this->request(['id' => $row['id']]);
|
|
|
+ $body = (new AnnouncementController())->delete($this->service)->getData(true);
|
|
|
+ $this->assertSame(0, $body['code']);
|
|
|
+ $this->assertSame(['id' => $row['id'], 'deleted' => true], $body['data']);
|
|
|
+ $this->assertSame(0, DB::table('announcements')->count());
|
|
|
+ $this->assertSame(0, DB::table('announcement_translations')->count());
|
|
|
+ $this->assertSame(0, $this->service->listing([])['total']);
|
|
|
+ $this->assertSame([], DB::table('site_realtime_events')->orderBy('id')->pluck('action')->all());
|
|
|
+ $this->assertSame('delete', DB::table('operation_audits')->orderByDesc('id')->value('action'));
|
|
|
+ $this->assertSame(-3, (new AnnouncementController())->delete($this->service)->getData(true)['code']);
|
|
|
+ $this->assertSame(2, DB::table('operation_audits')->count());
|
|
|
+ $this->assertSame(2, $this->service->logs([])['total']);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function test_announcement_deletion_never_notifies_and_all_pending_events_are_cancelled(): void
|
|
|
+ {
|
|
|
+ $active = $this->create();
|
|
|
+ $this->service->delete($active['id']);
|
|
|
+ $this->assertSame([], DB::table('site_realtime_events')->pluck('action')->all());
|
|
|
+ DB::table('site_realtime_events')->delete();
|
|
|
+ $future = $this->create(['publish_immediately' => false, 'publish_at' => '2026-10-26 11:00:00']);
|
|
|
+ DB::table('site_realtime_events')->insert(['module' => 'announcement', 'resource_id' => $future['id'], 'action' => 'create',
|
|
|
+ 'available_at' => '2026-10-26 10:00:00', 'created_at' => '2026-10-26 10:00:00']);
|
|
|
+ $this->service->delete($future['id']);
|
|
|
+ Carbon::setTestNow(Carbon::parse('2026-10-26 12:00:00', 'Asia/Shanghai'));
|
|
|
+ $this->assertSame(0, DB::table('site_realtime_events')->count());
|
|
|
+ }
|
|
|
+
|
|
|
+ public function test_delete_rolls_back_if_audit_or_notification_cannot_be_saved(): void
|
|
|
+ {
|
|
|
+ $row = $this->create();
|
|
|
+ Schema::drop('site_realtime_events');
|
|
|
+ try { $this->service->delete($row['id']); $this->fail('Missing event table must fail atomically'); }
|
|
|
+ catch (ValidationException $e) { $this->assertArrayHasKey('realtime', $e->errors()); }
|
|
|
+ $this->assertSame(1, DB::table('announcements')->count());
|
|
|
+ $this->assertSame(1, DB::table('announcement_translations')->count());
|
|
|
+ $this->assertSame(1, DB::table('operation_audits')->count());
|
|
|
+ }
|
|
|
+
|
|
|
public function test_controller_routes_are_authenticated_and_status_reuses_save_permission(): void
|
|
|
{
|
|
|
$router = new Router(new Dispatcher($this->app), $this->app);
|
|
|
@@ -293,6 +335,10 @@ class AnnouncementTest extends TestCase
|
|
|
$this->assertContains('admin.jwt', $route->middleware()); $this->assertContains('check.button.uri', $route->middleware());
|
|
|
}
|
|
|
$this->assertSame('admin/announcement/submit', $route->defaults['permission_uri']);
|
|
|
+ $delete = $router->getRoutes()->match(Request::create('/admin/announcement/delete', 'POST'));
|
|
|
+ $this->assertContains('admin.jwt', $delete->middleware());
|
|
|
+ $this->assertContains('check.button.uri', $delete->middleware());
|
|
|
+ $this->assertSame('delete', $delete->getActionMethod());
|
|
|
$this->request(['translations' => ['zh' => ['title' => '测试', 'content' => '内容']]]);
|
|
|
$result = (new AnnouncementController())->submit($this->service)->getData(true);
|
|
|
$this->assertSame(0, $result['code']);
|