Files
lotteryLaravel/tests/Feature/PlayerFoundationTest.php
kang e27a00f260 feat: 更新玩法配置管理,简化字段并增强功能
- 将玩法相关的显示名称字段统一为 `display_name`,移除多语言字段。
- 在 `PlayTypePatchController` 中新增即时切换玩法开关的功能,并推送大厅更新。
- 优化多个控制器和服务中的权限检查与数据处理逻辑,提升代码可读性与维护性。
2026-05-25 14:34:24 +08:00

130 lines
4.1 KiB
PHP

<?php
use Firebase\JWT\JWT;
use App\Models\Player;
use App\Lottery\ErrorCode;
use Symfony\Component\HttpFoundation\Response;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
test('player me returns profile with dev bearer', function () {
$player = Player::query()->create([
'site_code' => 'main',
'site_player_id' => 'uid-42',
'username' => 'alice',
'nickname' => 'A',
'default_currency' => 'NPR',
'status' => 0,
]);
$this->withHeaders([
'Authorization' => 'Bearer dev:'.$player->id,
'X-Locale' => 'zh',
])
->getJson('/api/v1/player/me')
->assertOk()
->assertJsonPath('code', ErrorCode::Success->value)
->assertJsonPath('data.id', $player->id)
->assertJsonPath('data.site_player_id', 'uid-42')
->assertJsonPath('data.username', 'alice')
->assertJsonPath('data.locale', 'zh')
->assertJsonStructure([
'data' => [
'last_login_at',
'created_at',
],
]);
$player->refresh();
expect($player->last_login_at)->not->toBeNull();
});
test('player auth missing bearer returns localized sso 8001', function () {
$code = ErrorCode::PlayerAuthorizationInvalid->value;
$this->withHeader('Accept-Language', 'zh-CN,zh;q=0.9')
->getJson('/api/v1/player/me')
->assertStatus(Response::HTTP_UNAUTHORIZED)
->assertJsonPath('code', $code)
->assertJsonPath('msg', __("sso.$code", [], 'zh'));
});
test('api unknown route returns unified not_found json without hitting locale middleware', function () {
$this->withHeader('X-Locale', 'zh')
->getJson('/api/v1/player/__no_route__xxx')
->assertStatus(Response::HTTP_NOT_FOUND)
->assertJsonPath('code', ErrorCode::NotFound->value)
->assertJsonPath('msg', __('api.not_found', [], 'zh'));
});
test('player me works with main site jwt when dev bypass is off', function () {
config(['lottery.player_auth.dev_bypass' => false]);
config(['lottery.main_site.sso_jwt_secret' => 'jwt-test-secret']);
$player = Player::query()->create([
'site_code' => 'main',
'site_player_id' => 'jwt-user-1',
'username' => null,
'nickname' => null,
'default_currency' => 'NPR',
'status' => 0,
]);
$now = time();
$jwt = JWT::encode([
'site_code' => 'main',
'site_player_id' => 'jwt-user-1',
'iat' => $now,
'exp' => $now + 300,
], 'jwt-test-secret', 'HS256');
$this->withHeader('Authorization', 'Bearer '.$jwt)
->getJson('/api/v1/player/me')
->assertOk()
->assertJsonPath('data.site_player_id', 'jwt-user-1');
});
test('jwt first successful login auto-registers player mapping', function () {
config(['lottery.player_auth.dev_bypass' => false]);
config(['lottery.main_site.sso_jwt_secret' => 'jwt-test-secret']);
expect(Player::query()->count())->toBe(0);
$now = time();
$jwt = JWT::encode([
'site_code' => 'main',
'site_player_id' => 'brand-new-sso-1',
'iat' => $now,
'exp' => $now + 300,
], 'jwt-test-secret', 'HS256');
$this->withHeader('Authorization', 'Bearer '.$jwt)
->getJson('/api/v1/player/me')
->assertOk()
->assertJsonPath('data.site_player_id', 'brand-new-sso-1')
->assertJsonPath('data.default_currency', 'NPR');
expect(Player::query()->where('site_player_id', 'brand-new-sso-1')->count())->toBe(1);
});
test('player me rejects non-active status with 8005', function () {
$code = ErrorCode::PlayerAccountSuspended->value;
$player = Player::query()->create([
'site_code' => 'main',
'site_player_id' => 'frozen-1',
'username' => null,
'nickname' => null,
'default_currency' => 'NPR',
'status' => 1,
]);
$this->withHeaders([
'Authorization' => 'Bearer dev:'.$player->id,
'Accept-Language' => 'zh-CN,zh;q=0.9',
])
->getJson('/api/v1/player/me')
->assertStatus(403)
->assertJsonPath('code', $code)
->assertJsonPath('msg', __("sso.$code", [], 'zh'));
});