Files
coruna-lab/tests/Feature/AdminAgentPortalTest.php
T
2026-08-11 02:26:43 +08:00

230 lines
8.1 KiB
PHP

<?php
namespace Tests\Feature;
use App\Models\Admin;
use App\Models\Channel;
use App\Models\Device;
use App\Models\User;
use App\Models\WalletAddress;
use App\Services\ChannelProjectService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Mockery;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
class AdminAgentPortalTest extends TestCase
{
use RefreshDatabase;
#[Test]
public function users_and_channels_tables_exist_via_models(): void
{
$user = User::query()->create([
'username' => 'agent1',
'password' => 'secret12',
'status' => 1,
'comment' => 'test',
]);
$channel = Channel::query()->create([
'channel_id' => 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
'user_id' => $user->id,
'status' => 1,
'remark' => 'demo',
]);
config([
'coruna.channel_domains' => ['cdn.example.com'],
'coruna.deployment_domains' => ['cdn.example.com'],
]);
$this->assertDatabaseHas('users', ['username' => 'agent1']);
$this->assertDatabaseHas('channels', ['channel_id' => $channel->channel_id, 'user_id' => $user->id]);
$this->assertSame(
['https://cdn.example.com/web/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/support.html'],
$channel->supportLinks()
);
}
#[Test]
public function disabled_agent_cannot_login(): void
{
User::query()->create([
'username' => 'disabled',
'password' => 'secret12',
'status' => 0,
]);
$this->post('/user/login', [
'username' => 'disabled',
'password' => 'secret12',
])->assertSessionHasErrors('username');
$this->assertGuest('agent');
}
#[Test]
public function enabled_agent_can_login(): void
{
User::query()->create([
'username' => 'okagent',
'password' => 'secret12',
'status' => 1,
]);
$this->post('/user/login', [
'username' => 'okagent',
'password' => 'secret12',
])->assertRedirect(route('user.home'));
$this->assertAuthenticated('agent');
}
#[Test]
public function admin_can_create_channel_with_random_id_and_links_fallback_domains(): void
{
config([
'coruna.channel_domains' => ['fallback.test'],
'coruna.deployment_domains' => ['fallback.test'],
]);
$admin = Admin::query()->create(['username' => 'admin', 'password' => 'admin123']);
$projects = Mockery::mock(ChannelProjectService::class);
$projects->shouldReceive('generate')->once()->andReturn([
'channel_id' => 'placeholder',
'seeds' => [
'deployment_seed' => '11111111111111111111111111111111',
'reporting_seed' => '11111111111111111111111111111111',
],
'domains' => ['deployment' => [], 'reporting' => []],
'seeds_initialized' => false,
'sync_rebuilt' => false,
'support_path' => '/web/x/support.html',
'daily_path' => '/sync/daily.html',
]);
$this->app->instance(ChannelProjectService::class, $projects);
$random = $this->actingAs($admin, 'admin')
->get(route('admin.channels.randomId'))
->assertOk()
->assertJsonPath('code', 0)
->json('data.channel_id');
$this->assertIsString($random);
$this->assertMatchesRegularExpression('/^[a-z0-9]{32}$/', $random);
$channelId = Channel::randomChannelId();
$this->assertMatchesRegularExpression('/^[a-z0-9]{32}$/', $channelId);
$this->actingAs($admin, 'admin')
->post(route('admin.channels.store'), [
'channel_id' => $channelId,
'user_id' => 0,
'remark' => 'official',
'status' => 1,
])
->assertOk()
->assertJsonPath('code', 0)
->assertJsonPath('data.links.0', 'https://fallback.test/web/'.$channelId.'/support.html');
$this->assertDatabaseHas('channels', [
'channel_id' => $channelId,
'user_id' => 0,
'remark' => 'official',
]);
}
#[Test]
public function agent_only_sees_own_channel_devices_and_addresses(): void
{
$agentA = User::query()->create(['username' => 'a', 'password' => 'secret12', 'status' => 1]);
$agentB = User::query()->create(['username' => 'b', 'password' => 'secret12', 'status' => 1]);
$chA = 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb';
$chB = 'cccccccccccccccccccccccccccccccc';
Channel::query()->create(['channel_id' => $chA, 'user_id' => $agentA->id, 'status' => 1]);
Channel::query()->create(['channel_id' => $chB, 'user_id' => $agentB->id, 'status' => 1]);
$devA = Device::query()->create([
'device_id' => 'dev-a',
'channel_id' => $chA,
'device_model' => 'iPhone',
]);
$devB = Device::query()->create([
'device_id' => 'dev-b',
'channel_id' => $chB,
'device_model' => 'iPhone',
]);
WalletAddress::query()->create([
'device_id' => $devA->id,
'address' => 'addr-a',
'source' => 'imToken',
'chain_type' => 'ETH',
]);
WalletAddress::query()->create([
'device_id' => $devB->id,
'address' => 'addr-b',
'source' => 'imToken',
'chain_type' => 'ETH',
]);
$this->actingAs($agentA, 'agent')
->getJson(route('user.devices.data'))
->assertOk()
->assertJsonPath('count', 1)
->assertJsonPath('data.0.device_id', 'dev-a');
$this->actingAs($agentA, 'agent')
->getJson(route('user.addresses.data'))
->assertOk()
->assertJsonPath('count', 1)
->assertJsonPath('data.0.address', 'addr-a');
$this->actingAs($agentA, 'agent')
->get(route('user.devices.show', $devB))
->assertForbidden();
}
#[Test]
public function admin_agent_filter_scopes_devices(): void
{
$admin = Admin::query()->create(['username' => 'admin', 'password' => 'admin123']);
$agent = User::query()->create(['username' => 'filter-me', 'password' => 'secret12', 'status' => 1]);
$ch = 'dddddddddddddddddddddddddddddddd';
Channel::query()->create(['channel_id' => $ch, 'user_id' => $agent->id, 'status' => 1]);
Device::query()->create(['device_id' => 'mine', 'channel_id' => $ch]);
Device::query()->create(['device_id' => 'other', 'channel_id' => 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee']);
$this->actingAs($admin, 'admin')
->getJson(route('admin.devices.data', ['agent_user_id' => $agent->id]))
->assertOk()
->assertJsonPath('count', 1)
->assertJsonPath('data.0.device_id', 'mine');
}
#[Test]
public function dashboard_counts_smoke(): void
{
$admin = Admin::query()->create(['username' => 'admin', 'password' => 'admin123']);
Device::query()->create(['device_id' => 'd1', 'channel_id' => 'ffffffffffffffffffffffffffffffff']);
Device::query()->create(['device_id' => 'd2', 'channel_id' => 'ffffffffffffffffffffffffffffffff']);
$this->actingAs($admin, 'admin')
->getJson(route('admin.dashboard.data', ['range' => '30d']))
->assertOk()
->assertJsonPath('code', 0)
->assertJsonPath('data.total', 2)
->assertJsonStructure(['data' => ['total', 'new_count', 'active_count', 'pv', 'uv', 'effective_pv', 'effective_uv', 'by_os', 'by_ios_version', 'from', 'to']]);
}
#[Test]
public function agent_cannot_create_channel(): void
{
$agent = User::query()->create(['username' => 'a', 'password' => 'secret12', 'status' => 1]);
$this->actingAs($agent, 'agent')
->post('/user/channels', [
'channel_id' => 'gggggggggggggggggggggggggggggggg',
'status' => 1,
])
->assertStatus(405);
}
}