feat: old channel
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\Admin;
|
||||
use App\Models\Channel;
|
||||
use App\Services\ChannelEmbedZipService;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use Tests\TestCase;
|
||||
use ZipArchive;
|
||||
|
||||
class ChannelEmbedZipTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
private const CHANNEL_ID = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
config([
|
||||
'coruna.channel_builder.artifact_root' => storage_path('app/channel-artifacts-test'),
|
||||
'coruna.channel_domains' => ['cdn.example.com'],
|
||||
'coruna.static_site.scheme' => 'https',
|
||||
]);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function admin_can_download_browser_embed_zip(): void
|
||||
{
|
||||
$dir = storage_path('app/channel-artifacts-test/web/'.self::CHANNEL_ID);
|
||||
if (! is_dir($dir) && ! mkdir($dir, 0775, true) && ! is_dir($dir)) {
|
||||
$this->fail('unable to create embed fixture dir');
|
||||
}
|
||||
file_put_contents($dir.'/index.js', "/* coruna-embed-boot */\nvar STAT_ORIGIN = '';\nvar CHANNEL = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';\n");
|
||||
file_put_contents($dir.'/payload.js', 'function cAsUcoxco(){}');
|
||||
file_put_contents($dir.'/deadbeef.js', '1');
|
||||
file_put_contents($dir.'/manifest.json', '{}');
|
||||
|
||||
$channel = Channel::query()->create([
|
||||
'channel_id' => self::CHANNEL_ID,
|
||||
'builder_type' => Channel::BUILDER_OLD,
|
||||
'user_id' => 0,
|
||||
'status' => 1,
|
||||
]);
|
||||
$admin = Admin::query()->create(['username' => 'admin', 'password' => 'admin123']);
|
||||
|
||||
$this->actingAs($admin, 'admin')
|
||||
->get(route('admin.channels.data'))
|
||||
->assertOk()
|
||||
->assertJsonPath('data.0.embed_script', '<script src="./index.js"></script>')
|
||||
->assertJsonPath('data.0.embed_zip_url', route('admin.channels.embedZip', $channel));
|
||||
|
||||
$this->actingAs($admin, 'admin')
|
||||
->get(route('admin.channels.embedZip', $channel))
|
||||
->assertOk()
|
||||
->assertDownload('channel-embed-'.self::CHANNEL_ID.'.zip');
|
||||
|
||||
$tmp = app(ChannelEmbedZipService::class)->build($channel);
|
||||
$this->assertFileExists($tmp);
|
||||
$zip = new ZipArchive();
|
||||
$this->assertTrue($zip->open($tmp) === true);
|
||||
$this->assertNotFalse($zip->locateName('index.js'));
|
||||
$this->assertNotFalse($zip->locateName('payload.js'));
|
||||
$this->assertNotFalse($zip->locateName('deadbeef.js'));
|
||||
$this->assertFalse($zip->locateName('manifest.json'));
|
||||
$boot = $zip->getFromName('index.js');
|
||||
$this->assertStringContainsString('https://cdn.example.com', (string) $boot);
|
||||
$this->assertStringNotContainsString('c2.example.com', (string) $boot);
|
||||
$this->assertStringContainsString('<script src="./index.js"></script>', (string) $zip->getFromName('README.txt'));
|
||||
$zip->close();
|
||||
@unlink($tmp);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function zip_service_lists_only_browser_files(): void
|
||||
{
|
||||
$dir = storage_path('app/channel-artifacts-test/channel/3.1.07/weifile');
|
||||
if (! is_dir($dir) && ! mkdir($dir, 0775, true) && ! is_dir($dir)) {
|
||||
$this->fail('unable to create weifile fixture dir');
|
||||
}
|
||||
file_put_contents($dir.'/index.js', '/* coruna-embed-boot */');
|
||||
file_put_contents($dir.'/payload.js', 'payload');
|
||||
file_put_contents($dir.'/weifile.html', '<script src="index.js"></script>');
|
||||
|
||||
$channel = new Channel([
|
||||
'channel_id' => '3.1.07',
|
||||
'builder_type' => Channel::BUILDER_NEW,
|
||||
]);
|
||||
|
||||
$files = app(ChannelEmbedZipService::class)->listFiles($channel);
|
||||
$this->assertSame(['index.js', 'payload.js', 'weifile.html'], $files);
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@ 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.seed' => '11111111111111111111111111111111',
|
||||
'coruna.channel_builder_new.python' => 'python3',
|
||||
'coruna.channel_builder_new.state_root' => storage_path('app/channel-builder-new-test'),
|
||||
'coruna.channel_domains' => ['fallback.test'],
|
||||
@@ -102,12 +103,15 @@ class ChannelProjectServiceTest extends TestCase
|
||||
return str_contains($joined, 'new_project.py')
|
||||
&& str_contains($joined, self::CHANNEL_ID)
|
||||
&& str_contains($joined, '--support-template')
|
||||
&& str_contains($joined, 'blank');
|
||||
&& str_contains($joined, 'blank')
|
||||
&& str_contains($joined, '--deployment-seed')
|
||||
&& str_contains($joined, '11111111111111111111111111111111')
|
||||
&& str_contains($joined, '--reporting-seed');
|
||||
});
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_forwards_optional_seeds_to_builder(): void
|
||||
public function it_forwards_env_seed_and_ignores_request_seeds(): void
|
||||
{
|
||||
Process::fake([
|
||||
'*' => Process::result(output: $this->fakeBuildResult(['seeds_initialized' => false, 'sync_rebuilt' => false])),
|
||||
@@ -116,41 +120,30 @@ class ChannelProjectServiceTest extends TestCase
|
||||
app(ChannelProjectService::class)->generate(
|
||||
self::CHANNEL_ID,
|
||||
'test',
|
||||
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
|
||||
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
|
||||
'cccccccccccccccccccccccccccccccc',
|
||||
'dddddddddddddddddddddddddddddddd',
|
||||
);
|
||||
|
||||
Process::assertRan(function ($process) {
|
||||
$joined = is_array($process->command) ? implode(' ', $process->command) : (string) $process->command;
|
||||
|
||||
return str_contains($joined, '--deployment-seed')
|
||||
&& str_contains($joined, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
|
||||
&& str_contains($joined, '11111111111111111111111111111111')
|
||||
&& str_contains($joined, '--reporting-seed')
|
||||
&& substr_count($joined, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') >= 2;
|
||||
&& ! str_contains($joined, 'cccccccccccccccccccccccccccccccc')
|
||||
&& ! str_contains($joined, 'dddddddddddddddddddddddddddddddd');
|
||||
});
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_rejects_partial_seed_pair(): void
|
||||
public function old_builder_requires_env_seed(): void
|
||||
{
|
||||
config(['coruna.channel_builder.seed' => '']);
|
||||
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->expectExceptionMessage('deployment_seed 与 reporting_seed 必须同时提供');
|
||||
$this->expectExceptionMessage('CORUNA_CHANNEL_SEED');
|
||||
|
||||
app(ChannelProjectService::class)->generate(self::CHANNEL_ID, 'test', 'only-one', null);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_rejects_mismatched_seed_pair(): void
|
||||
{
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->expectExceptionMessage('deployment_seed 与 reporting_seed 必须相同');
|
||||
|
||||
app(ChannelProjectService::class)->generate(
|
||||
self::CHANNEL_ID,
|
||||
'test',
|
||||
'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
|
||||
'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
|
||||
);
|
||||
app(ChannelProjectService::class)->generate(self::CHANNEL_ID, 'test');
|
||||
}
|
||||
|
||||
#[Test]
|
||||
@@ -664,6 +657,89 @@ class ChannelProjectServiceTest extends TestCase
|
||||
});
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_rebuilds_existing_old_channels_in_place(): void
|
||||
{
|
||||
$otherOld = 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb';
|
||||
Channel::query()->create([
|
||||
'channel_id' => self::CHANNEL_ID,
|
||||
'builder_type' => Channel::BUILDER_OLD,
|
||||
'user_id' => 0,
|
||||
'status' => 1,
|
||||
]);
|
||||
Channel::query()->create([
|
||||
'channel_id' => $otherOld,
|
||||
'builder_type' => Channel::BUILDER_OLD,
|
||||
'user_id' => 0,
|
||||
'status' => 1,
|
||||
]);
|
||||
Channel::query()->create([
|
||||
'channel_id' => self::NEW_CHANNEL_ID,
|
||||
'builder_type' => Channel::BUILDER_NEW,
|
||||
'user_id' => 0,
|
||||
'status' => 1,
|
||||
]);
|
||||
Process::fake([
|
||||
'*' => Process::result(output: $this->fakeBuildResult()),
|
||||
]);
|
||||
|
||||
$result = app(ChannelProjectService::class)->rebuildOldChannels();
|
||||
|
||||
$this->assertCount(2, $result['channels']);
|
||||
|
||||
Process::assertRanTimes(function ($process) {
|
||||
$joined = is_array($process->command) ? implode(' ', $process->command) : (string) $process->command;
|
||||
|
||||
return str_contains($joined, 'new_project.py')
|
||||
&& str_contains($joined, '--deployment-seed')
|
||||
&& str_contains($joined, '11111111111111111111111111111111');
|
||||
}, 2);
|
||||
Process::assertRan(function ($process) {
|
||||
$joined = is_array($process->command) ? implode(' ', $process->command) : (string) $process->command;
|
||||
|
||||
return str_contains($joined, 'new_project.py') && str_contains($joined, self::CHANNEL_ID);
|
||||
});
|
||||
Process::assertRan(function ($process) {
|
||||
$joined = is_array($process->command) ? implode(' ', $process->command) : (string) $process->command;
|
||||
|
||||
return str_contains($joined, 'new_project.py') && str_contains($joined, 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb');
|
||||
});
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_rejects_invalid_old_channel_ids_when_repacking(): void
|
||||
{
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->expectExceptionMessage('旧版渠道 ID 必须是 32 位 hex');
|
||||
|
||||
app(ChannelProjectService::class)->resolveOldChannelIds(['not-a-channel']);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function coruna_repack_dry_run_lists_old_channels(): void
|
||||
{
|
||||
Channel::query()->create([
|
||||
'channel_id' => self::CHANNEL_ID,
|
||||
'builder_type' => Channel::BUILDER_OLD,
|
||||
'user_id' => 0,
|
||||
'status' => 1,
|
||||
]);
|
||||
Channel::query()->create([
|
||||
'channel_id' => self::NEW_CHANNEL_ID,
|
||||
'builder_type' => Channel::BUILDER_NEW,
|
||||
'user_id' => 0,
|
||||
'status' => 1,
|
||||
]);
|
||||
Process::fake();
|
||||
|
||||
$this->artisan('coruna:repack', ['--dry-run' => true])
|
||||
->expectsOutputToContain('将重打 1 个旧版渠道')
|
||||
->expectsOutputToContain('/web/'.self::CHANNEL_ID.'/support.html')
|
||||
->assertSuccessful();
|
||||
|
||||
Process::assertNothingRan();
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function version_format_required_for_new_channel_ids(): void
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user