Files
ulthon_admin/tests/Feature/NoticeEventTest.php
2026-10-12 13:40:40 +00:00

164 lines
6.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
namespace tests\Feature;
use app\admin\model\SystemAdmin;
use app\common\event\AdminLoginSuccess\NoticeEvent;
use app\common\service\NoticeService;
use app\common\test\TestCase;
use think\facade\Cache;
use think\facade\Db;
use think\facade\Event;
/**
* 事件层集成测试.
*
* 覆盖:
* 1. send 触发 NoticeSended 事件,payload = [$notice(模型), $targets(投递行数组)]
* 2. 登录提醒开关开启时 NoticeEvent 落 admin_login 通知(inmail 行直接成功终态)
* 3. 开关默认关闭(无配置行)时不发
*
* fixture 均为事务内自造数据,tearDown 自动回滚;sysconfig 缓存显式清理
* (Cache 不受事务回滚影响,非 '0' 值会缓存 3600 秒)。
*/
class NoticeEventTest extends TestCase
{
// =========================================================================
// 1. NoticeSended 事件触发
// =========================================================================
public function test_send_triggers_notice_sended_event_with_notice_and_targets(): void
{
$adminId = $this->createAdmin();
// 临时注入收集器监听器(容器内与框架注册的 NoticeSended LogEvent 并存,互不影响)
$captured = [];
Event::listen('NoticeSended', function ($payload) use (&$captured) {
$captured[] = $payload;
});
$noticeId = NoticeService::send([$adminId], '事件测试', '内容');
$this->assertCount(1, $captured, 'send 应触发一次 NoticeSended 事件');
[$notice, $targets] = $captured[0];
$this->assertSame($noticeId, (int) $notice->id, 'payload[0] 应为本次创建的 notice 模型');
$this->assertIsArray($targets, 'payload[1] 应为投递行数组');
$this->assertCount(1, $targets);
$this->assertSame($adminId, (int) $targets[0]['admin_id']);
$this->assertSame('inmail', $targets[0]['channel']);
}
// =========================================================================
// 2. 登录提醒开关开启:NoticeEvent 落 admin_login 通知
// =========================================================================
public function test_login_notice_sent_when_scene_switch_on(): void
{
$adminId = $this->createAdmin(['username' => 'lgn_' . uniqid()]);
$admin = SystemAdmin::find($adminId);
$this->assertNotNull($admin, 'SystemAdmin 模型应能取到监听器入参形态');
$this->setLoginSceneSwitch('1');
(new NoticeEvent())->handle($admin);
$row = Db::name('system_notice')
->where('scene', 'admin_login')
->where('send_admin_id', 0)
->find();
$this->assertNotNull($row, '开关开启时应产生 admin_login 通知主体');
$this->assertSame('登录提醒', $row['title']);
// 文案含登录时间(Y-m-d H:i),跨分钟竞态下按正则断言而非逐字相等
$pattern = '/^账号 ' . preg_quote((string) $admin->username, '/') . ' 于 \d{4}-\d{2}-\d{2} \d{2}:\d{2} 登录成功$/u';
$this->assertMatchesRegularExpression($pattern, (string) $row['content']);
// inmail 行直接成功终态(无 email 地址的管理员 email 渠道被跳过)
$this->assertDatabaseHas('system_notice_target', [
'notice_id' => $row['id'],
'admin_id' => $adminId,
'channel' => 'inmail',
'status' => 2,
]);
$this->assertSame(
1,
Db::name('system_notice_target')->where('notice_id', $row['id'])->count(),
'无 email 管理员应仅展开 inmail 一行'
);
}
// =========================================================================
// 3. 登录提醒开关默认关闭
// =========================================================================
public function test_login_notice_skipped_when_scene_switch_absent(): void
{
$adminId = $this->createAdmin(['username' => 'lgn_' . uniqid()]);
$admin = SystemAdmin::find($adminId);
// 无配置行 = 默认关;清理可能被前序用例缓存的非 '0' 值
$this->clearLoginSceneSwitch();
(new NoticeEvent())->handle($admin);
$this->assertSame(
0,
Db::name('system_notice')->where('scene', 'admin_login')->where('send_admin_id', 0)->count(),
'开关缺省(无配置行)时不应产生 admin_login 通知'
);
}
// =========================================================================
// fixture 工厂(事务内运行,tearDown 自动回滚)
// =========================================================================
/**
* 造启用管理员.
*/
private function createAdmin(array $overrides = []): int
{
$data = array_merge([
'username' => 'evt_' . uniqid(),
'password' => 'not-a-real-password',
'nickname' => '事件测试用户',
'email' => '',
'status' => 1,
'create_time' => time(),
'update_time' => time(),
'delete_time' => 0,
], $overrides);
return (int) Db::name('system_admin')->insertGetId($data);
}
/**
* 写 notify 组登录提醒开关配置行并清缓存(缓存不受事务回滚影响).
*/
private function setLoginSceneSwitch(string $value): void
{
Db::name('system_config')->insert([
'name' => 'notify_login_scene_enable',
'group' => 'notify',
'value' => $value,
'remark' => 'NoticeEventTest fixture',
'sort' => 100,
'create_time' => time(),
'update_time' => time(),
]);
Cache::tag('sysconfig')->clear();
}
/**
* 删除 notify 组登录提醒开关配置行并清缓存.
*/
private function clearLoginSceneSwitch(): void
{
Db::name('system_config')
->where('group', 'notify')
->where('name', 'notify_login_scene_enable')
->delete();
Cache::tag('sysconfig')->clear();
}
}