feat: xxbb

This commit is contained in:
hashbro
2026-08-13 06:30:07 +08:00
parent f285d35d86
commit c6e386e069
121 changed files with 4083 additions and 51 deletions
+171
View File
@@ -27,6 +27,8 @@ class ChannelProjectServiceTest extends TestCase
'coruna.channel_builder.python' => 'python3',
'coruna.channel_builder.artifact_root' => storage_path('app/channel-artifacts-test'),
'coruna.channel_builder.timeout' => 30,
'coruna.channel_builder_new.python' => 'python3',
'coruna.channel_builder_new.state_root' => storage_path('app/channel-builder-new-test'),
'coruna.channel_domains' => ['fallback.test'],
]);
}
@@ -325,5 +327,174 @@ class ChannelProjectServiceTest extends TestCase
$this->assertDatabaseHas('channels', ['channel_id' => self::CHANNEL_ID]);
$channel = Channel::query()->where('channel_id', self::CHANNEL_ID)->first();
$this->assertSame([], $channel->domains ?? []);
$this->assertSame(Channel::BUILDER_OLD, $channel->builderType());
$this->assertNull($channel->channel_name);
}
#[Test]
public function it_invokes_new_builder_with_channel_name(): void
{
$name = 'abcd1234';
Process::fake([
'*' => Process::result(output: $this->fakeBuildResult([
'builder_type' => 'new',
'channel_name' => $name,
'weifile_path' => '/source/'.$name.'/index.html',
'support_path' => '/source/'.$name.'/index.html',
'daily_path' => '',
'domains' => ['deployment' => [], 'reporting' => []],
])),
]);
$result = app(ChannelProjectService::class)->generate(
self::CHANNEL_ID,
'test',
null,
null,
Channel::BUILDER_NEW,
$name,
);
$this->assertSame(Channel::BUILDER_NEW, $result['builder_type']);
$this->assertSame($name, $result['channel_name']);
$this->assertSame('/source/'.$name.'/index.html', $result['weifile_path']);
$this->assertSame('/source/'.$name.'/index.html', $result['support_path']);
Process::assertRan(function ($process) use ($name) {
$joined = is_array($process->command) ? implode(' ', $process->command) : (string) $process->command;
return str_contains($joined, 'build.py')
&& str_contains($joined, '--channel-name')
&& str_contains($joined, $name)
&& str_contains($joined, '--channel-c')
&& str_contains($joined, self::CHANNEL_ID)
&& str_contains($joined, '--scheme')
&& str_contains($joined, '--apply')
&& str_contains($joined, '--force');
});
}
#[Test]
public function new_builder_rejects_mismatched_seeds(): void
{
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('deployment_seed 与 reporting_seed 必须相同');
app(ChannelProjectService::class)->generate(
self::CHANNEL_ID,
'test',
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
Channel::BUILDER_NEW,
'abcd1234',
);
}
#[Test]
public function support_links_use_channel_name_path_for_new_builder(): void
{
$channel = new Channel([
'channel_id' => self::CHANNEL_ID,
'builder_type' => Channel::BUILDER_NEW,
'channel_name' => 'abcd1234',
'domains' => ['channel.test'],
]);
$this->assertSame([
'https://channel.test/source/abcd1234/index.html',
], $channel->supportLinks());
$this->assertSame('/source/abcd1234/index.html', $channel->landingPath());
}
#[Test]
public function store_new_builder_persists_channel_name_and_returns_weifile_path(): void
{
Process::fake([
'*' => Process::result(output: $this->fakeBuildResult([
'weifile_path' => '/placeholder/placeholder.html',
'support_path' => '/placeholder/placeholder.html',
'daily_path' => '',
])),
]);
$admin = Admin::query()->create(['username' => 'admin', 'password' => 'admin123']);
$response = $this->actingAs($admin, 'admin')
->post(route('admin.channels.store'), [
'channel_id' => self::CHANNEL_ID,
'builder_type' => Channel::BUILDER_NEW,
'user_id' => 0,
])
->assertOk()
->assertJsonPath('code', 0)
->assertJsonPath('data.builder_type', Channel::BUILDER_NEW);
$channel = Channel::query()->where('channel_id', self::CHANNEL_ID)->first();
$this->assertNotNull($channel);
$this->assertSame(Channel::BUILDER_NEW, $channel->builderType());
$this->assertMatchesRegularExpression('/^[a-z0-9]{8}$/', (string) $channel->channel_name);
$this->assertSame(
'/source/'.$channel->channel_name.'/index.html',
$channel->landingPath()
);
$this->assertSame($channel->channel_name, $response->json('data.channel_name'));
$this->assertSame($channel->landingPath(), $response->json('data.weifile_path'));
Process::assertRan(function ($process) use ($channel) {
$joined = is_array($process->command) ? implode(' ', $process->command) : (string) $process->command;
return str_contains($joined, 'build.py')
&& str_contains($joined, $channel->channel_name)
&& str_contains($joined, '--channel-c')
&& str_contains($joined, self::CHANNEL_ID);
});
}
#[Test]
public function destroy_new_builder_deletes_channel_name_tree(): void
{
Process::fake([
'*' => Process::result(output: ChannelProjectService::RESULT_MARKER.json_encode([
'status' => 'deleted',
'removed' => true,
])."\n"),
]);
$admin = Admin::query()->create(['username' => 'admin', 'password' => 'admin123']);
$channel = Channel::query()->create([
'channel_id' => self::CHANNEL_ID,
'builder_type' => Channel::BUILDER_NEW,
'channel_name' => 'abcd1234',
'user_id' => 0,
'status' => 1,
]);
$this->actingAs($admin, 'admin')
->delete(route('admin.channels.destroy', $channel))
->assertOk()
->assertJsonPath('code', 0);
Process::assertRan(function ($process) {
$joined = is_array($process->command) ? implode(' ', $process->command) : (string) $process->command;
return str_contains($joined, 'delete_channel.py')
&& str_contains($joined, 'abcd1234')
&& ! str_contains($joined, 'delete_channel_web.py');
});
$this->assertDatabaseMissing('channels', ['id' => $channel->id]);
}
#[Test]
public function random_channel_name_is_unique_and_not_reserved(): void
{
Channel::query()->create([
'channel_id' => self::CHANNEL_ID,
'builder_type' => Channel::BUILDER_NEW,
'channel_name' => 'taken123',
'user_id' => 0,
'status' => 1,
]);
$name = Channel::randomChannelName();
$this->assertMatchesRegularExpression('/^[a-z0-9]{8}$/', $name);
$this->assertNotSame('taken123', $name);
$this->assertFalse(Channel::isReservedChannelName($name));
}
}