dootask/tests/Unit/UserImportParseTest.php
kuaifan 645cb02757 chore(upgrade): Laravel 8 直升 13(旧结构跑通)+ PHP 8.4 + 依赖升级与兼容修复
- composer: framework ^13.0、php ^8.3、laravel-s ~3.8.0、predis ^2.3、
  phpunit ^11.5、tinker ^3、excel ^3.1.69、captcha ^3.5、avatar ^6.5、
  ldaprecord-laravel ^4、pinyin ^5.3、notify 锁 ~1.28.0;
  移除 fideloper/proxy、fruitcake/laravel-cors、facade/ignition、
  laravel/sail、madnest/madzipper、手动钉的 symfony/mailer;
  symfony/console 锁 ^7.4(LaravelS Portal 与 console 8 的
  configure(): void 类型断言不兼容)
- $dates 移除:AbstractModel 改 getCasts() 合并默认 datetime 列,
  3 个子模型改 $casts
- Carbon 3:4 处 diffInSeconds 补 absolute 参数并取整
- LdapRecord v4:config use_ssl/use_tls→use_tls/use_starttls(env 变量名不变),
  LdapUser::$objectClasses 补类型声明
- Madzipper→原生 ZipArchive(Base::zipAddFiles,4 处调用)
- pinyin v5 静态 API(Base::getFirstCharter/cn2pinyin)
- laravolt/avatar 6.5:PatchedAvatar 修上游纵向对齐 bug
 (intervention 4.1.3 枚举无 middle),avatar 响应改 response()->file()
- TrustProxies 改框架内置基类,CORS 改 Illuminate\Http\Middleware\HandleCors
- Symfony Console 8 兼容:ManticoreSyncLock::handleSignal 新签名,
  pcntl 回调解耦
- 非 Swoole 运行时守卫:AbstractTask::task / PushTask::push /
  AbstractData(swoole table),artisan/测试上下文不再炸
  Target class [swoole] does not exist
- Laravel 11+ change() 丢修饰符:2023_12_07 与 2025_08_10 迁移重申
  nullable/default/comment(修复 fresh 安装)
- Setting/Ihttp 缺键访问加 ?? 守卫(PHP 8 警告在测试中转异常)
- phpunit.xml 迁移 11 schema;UserImportParseTest 改为自建部门数据

验证:8.4 容器内 migrate:fresh --seed 213 全过;php artisan test
145 passed/1 skipped;LaravelS(Swoole 6.2.1) /health 200、登录、
token 认证、WebSocket 握手、Task 投递、头像、图片裁剪冒烟全过

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 19:42:12 +00:00

148 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
namespace Tests\Unit;
use App\Models\User;
use App\Models\UserDepartment;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\TestCase;
class UserImportParseTest extends TestCase
{
use DatabaseTransactions;
public function test_parse_skips_header_and_empty_rows()
{
$sheet = [
['邮箱', '昵称', '初始密码'], // 表头,应跳过
['a@test.local', '张三', 'Abc123456'],
['', '', ''], // 空行,应跳过
['b@test.local', '李四', 'Xyz123456'],
];
$rows = User::parseImportRows($sheet);
$this->assertCount(2, $rows);
$this->assertSame('a@test.local', $rows[0]['email']);
$this->assertSame('张三', $rows[0]['nickname']);
$this->assertSame('Abc123456', $rows[0]['password']);
$this->assertSame(2, $rows[0]['line']);
$this->assertSame(4, $rows[1]['line']);
}
public function test_parse_trims_cells()
{
$sheet = [
['邮箱', '昵称', '初始密码'],
[' a@test.local ', ' 张三 ', ' Abc123456 '],
];
$rows = User::parseImportRows($sheet);
$this->assertSame('a@test.local', $rows[0]['email']);
$this->assertSame('张三', $rows[0]['nickname']);
$this->assertSame('Abc123456', $rows[0]['password']);
}
public function test_validate_passes_for_valid_row()
{
$row = ['email' => 'ok@test.local', 'nickname' => '张三', 'password' => 'Abc123456'];
$this->assertNull(User::validateImportRow($row));
}
public function test_validate_requires_all_fields()
{
$this->assertSame('邮箱、昵称、初始密码均为必填', User::validateImportRow(['email' => '', 'nickname' => '张三', 'password' => 'Abc123456']));
$this->assertSame('邮箱、昵称、初始密码均为必填', User::validateImportRow(['email' => 'a@test.local', 'nickname' => '', 'password' => 'Abc123456']));
$this->assertSame('邮箱、昵称、初始密码均为必填', User::validateImportRow(['email' => 'a@test.local', 'nickname' => '张三', 'password' => '']));
}
public function test_validate_rejects_bad_email()
{
$this->assertSame('邮箱格式不正确', User::validateImportRow(['email' => 'not-an-email', 'nickname' => '张三', 'password' => 'Abc123456']));
}
public function test_validate_rejects_bad_nickname_length()
{
$this->assertSame('昵称需为2-20个字', User::validateImportRow(['email' => 'a@test.local', 'nickname' => '王', 'password' => 'Abc123456']));
$this->assertSame('昵称需为2-20个字', User::validateImportRow(['email' => 'a@test.local', 'nickname' => str_repeat('字', 21), 'password' => 'Abc123456']));
}
public function test_validate_rejects_short_password()
{
$this->assertNotNull(User::validateImportRow(['email' => 'a@test.local', 'nickname' => '张三', 'password' => '123']));
}
public function test_assert_valid_profession_passes_for_empty_and_normal()
{
// 空职位允许可选字段2/20 字边界与正常值允许;不抛异常即通过
User::assertValidProfession('');
User::assertValidProfession('工程'); // 恰好 2 字
User::assertValidProfession('工程师');
User::assertValidProfession(str_repeat('字', 20)); // 恰好 20 字
$this->assertTrue(true);
}
public function test_assert_valid_profession_rejects_too_short()
{
$this->expectException(\App\Exceptions\ApiException::class);
$this->expectExceptionMessage('职位/职称不可以少于2个字');
User::assertValidProfession('A');
}
public function test_assert_valid_profession_rejects_too_long()
{
$this->expectException(\App\Exceptions\ApiException::class);
$this->expectExceptionMessage('职位/职称最多只能设置20个字');
User::assertValidProfession(str_repeat('字', 21));
}
public function test_assert_valid_departments_normalizes_ids()
{
// 空/非数组 → 返回空数组
$this->assertSame([], User::assertValidDepartments([]));
$this->assertSame([], User::assertValidDepartments('not-array'));
// 去重 + 转 int + 过滤非正数(存在性校验会查库,需用真实部门 ID
$deptA = UserDepartment::createInstance(['name' => 'ImportParseDeptA_' . uniqid()]);
$deptA->save();
$deptB = UserDepartment::createInstance(['name' => 'ImportParseDeptB_' . uniqid()]);
$deptB->save();
$a = $deptA->id;
$b = $deptB->id;
$this->assertSame([$a, $b], User::assertValidDepartments([(string)$a, $a, $b, 0, -1]));
}
public function test_assert_valid_departments_rejects_over_limit()
{
// 超过 10 个count 校验在查库之前)→ 抛异常
$this->expectException(\App\Exceptions\ApiException::class);
$this->expectExceptionMessage('最多只可加入10个部门');
User::assertValidDepartments(range(1, 11));
}
public function test_parse_reads_profession_column()
{
$sheet = [
['邮箱', '昵称', '初始密码', '职位'],
['a@test.local', '张三', 'Abc123456', '工程师'],
['b@test.local', '李四', 'Xyz123456'], // 无职位列 → profession 为空
];
$rows = User::parseImportRows($sheet);
$this->assertCount(2, $rows);
$this->assertSame('工程师', $rows[0]['profession']);
$this->assertSame('', $rows[1]['profession']);
}
public function test_validate_passes_for_empty_profession()
{
$row = ['email' => 'a@test.local', 'nickname' => '张三', 'password' => 'Abc123456', 'profession' => ''];
$this->assertNull(User::validateImportRow($row));
}
public function test_validate_rejects_bad_profession()
{
$row = ['email' => 'a@test.local', 'nickname' => '张三', 'password' => 'Abc123456', 'profession' => 'A'];
$this->assertSame('职位/职称不可以少于2个字', User::validateImportRow($row));
}
}