mirror of
https://gitee.com/ulthon/ulthon_admin.git
synced 2026-11-07 19:40:49 +08:00
feat(notice): NoticeSended 事件与登录提醒内置监听
This commit is contained in:
163
tests/Feature/NoticeEventTest.php
Normal file
163
tests/Feature/NoticeEventTest.php
Normal file
@@ -0,0 +1,163 @@
|
||||
<?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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user