cf-removal: add v0.10.0 migration + tests
New class PRAutoBlogger_Migrate_Remove_Cloudflare_V0100 (own file so class-activator.php stays under 300 lines). Runs from PRAutoBlogger::maybe_run_db_migrations() right after the v0.9.0 migration. Idempotent via prautoblogger_migrated_remove_cloudflare_v0100 flag option (picked up by the uninstall prefix sweep). Migrates any user on a Cloudflare image provider to Runware FLUX.1 schnell (closest equivalent, ~bash.0006/image). Detects the three shapes a legacy user can be in: registry-derived provider === 'cloudflare', image_provider option === 'cloudflare', or the legacy slug 'flux-1-schnell'. Cleans up three now-dead options: prautoblogger_cloudflare_ai_token, prautoblogger_cloudflare_account_id, prautoblogger_cf_image_via_gateway. Does NOT touch prautoblogger_ai_gateway_base_url — that option is shared with the OpenRouter AI Gateway route and must stay (live- verified test). Tests (tests/unit/Core/ActivatorRemoveCloudflareTest.php): - cloudflare user → runware schnell - non-cloudflare user preserved - runware user preserved - legacy 'flux-1-schnell' slug triggers migration - second run is a no-op (does not clobber admin manual changes) - AI Gateway URL preserved across every path ImageModelRegistryTest updated: allowed-provider set is now ['runware','openrouter']; new test_cloudflare_entries_removed_v0100 test pins the scope boundary.
This commit is contained in:
163
tests/unit/Core/ActivatorRemoveCloudflareTest.php
Normal file
163
tests/unit/Core/ActivatorRemoveCloudflareTest.php
Normal file
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
/**
|
||||
* Tests for the v0.10.0 one-shot migration that removes Cloudflare
|
||||
* Workers AI as an image provider — exercises the cloudflare-user
|
||||
* path, the non-cloudflare-user path, idempotency, and the critical
|
||||
* scope-boundary invariant that `prautoblogger_ai_gateway_base_url`
|
||||
* (shared with the OpenRouter AI Gateway route) is left intact.
|
||||
*
|
||||
* See thread 2026-04-cloudflare-workers-ai-removal/01-cto-handoff.md.
|
||||
*
|
||||
* @package PRAutoBlogger\Tests\Core
|
||||
*/
|
||||
|
||||
namespace PRAutoBlogger\Tests\Core;
|
||||
|
||||
use PRAutoBlogger\Tests\BaseTestCase;
|
||||
use Brain\Monkey\Functions;
|
||||
|
||||
class ActivatorRemoveCloudflareTest extends BaseTestCase {
|
||||
|
||||
/** @var array<string, mixed> */
|
||||
private array $options = [];
|
||||
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->options = [];
|
||||
|
||||
Functions\when( 'get_option' )->alias(
|
||||
fn( $key, $default = false ) => $this->options[ $key ] ?? $default
|
||||
);
|
||||
Functions\when( 'update_option' )->alias(
|
||||
function ( $key, $value ) {
|
||||
$this->options[ $key ] = $value;
|
||||
return true;
|
||||
}
|
||||
);
|
||||
Functions\when( 'delete_option' )->alias(
|
||||
function ( $key ) {
|
||||
unset( $this->options[ $key ] );
|
||||
return true;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cloudflare user: flipped to Runware schnell, CF credentials removed,
|
||||
* gateway URL preserved, flag set.
|
||||
*/
|
||||
public function test_cloudflare_user_migrated_to_runware(): void {
|
||||
$this->options = [
|
||||
'prautoblogger_image_provider' => 'cloudflare',
|
||||
'prautoblogger_image_model' => 'flux-1-schnell',
|
||||
'prautoblogger_cloudflare_ai_token' => 'enc:SECRET',
|
||||
'prautoblogger_cloudflare_account_id' => 'acct-123',
|
||||
'prautoblogger_cf_image_via_gateway' => '1',
|
||||
// Shared with OpenRouter AI Gateway — MUST be preserved.
|
||||
'prautoblogger_ai_gateway_base_url' => 'https://gateway.ai.cloudflare.com/v1/acct/gw/openrouter',
|
||||
];
|
||||
|
||||
\PRAutoBlogger_Migrate_Remove_Cloudflare_V0100::run();
|
||||
|
||||
$this->assertSame( 'runware', $this->options['prautoblogger_image_provider'] );
|
||||
$this->assertSame( 'runware:100@1', $this->options['prautoblogger_image_model'] );
|
||||
|
||||
$this->assertArrayNotHasKey( 'prautoblogger_cloudflare_ai_token', $this->options );
|
||||
$this->assertArrayNotHasKey( 'prautoblogger_cloudflare_account_id', $this->options );
|
||||
$this->assertArrayNotHasKey( 'prautoblogger_cf_image_via_gateway', $this->options );
|
||||
|
||||
$this->assertSame(
|
||||
'https://gateway.ai.cloudflare.com/v1/acct/gw/openrouter',
|
||||
$this->options['prautoblogger_ai_gateway_base_url'],
|
||||
'AI Gateway URL (shared with OpenRouter route) must NOT be touched.'
|
||||
);
|
||||
|
||||
$this->assertSame( '1', $this->options['prautoblogger_migrated_remove_cloudflare_v0100'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Non-Cloudflare user (e.g. already on OpenRouter Gemini): model +
|
||||
* provider untouched; CF credentials still swept; flag set.
|
||||
*/
|
||||
public function test_non_cloudflare_user_preserved(): void {
|
||||
$this->options = [
|
||||
'prautoblogger_image_provider' => 'openrouter',
|
||||
'prautoblogger_image_model' => 'google/gemini-2.5-flash-image',
|
||||
// Hypothetical orphans from an earlier experiment.
|
||||
'prautoblogger_cloudflare_ai_token' => 'enc:OLD',
|
||||
'prautoblogger_cloudflare_account_id' => 'acct-999',
|
||||
'prautoblogger_ai_gateway_base_url' => 'https://gateway.ai.cloudflare.com/v1/acct/gw/openrouter',
|
||||
];
|
||||
|
||||
\PRAutoBlogger_Migrate_Remove_Cloudflare_V0100::run();
|
||||
|
||||
$this->assertSame( 'openrouter', $this->options['prautoblogger_image_provider'] );
|
||||
$this->assertSame( 'google/gemini-2.5-flash-image', $this->options['prautoblogger_image_model'] );
|
||||
|
||||
$this->assertArrayNotHasKey( 'prautoblogger_cloudflare_ai_token', $this->options );
|
||||
$this->assertArrayNotHasKey( 'prautoblogger_cloudflare_account_id', $this->options );
|
||||
$this->assertSame(
|
||||
'https://gateway.ai.cloudflare.com/v1/acct/gw/openrouter',
|
||||
$this->options['prautoblogger_ai_gateway_base_url']
|
||||
);
|
||||
$this->assertSame( '1', $this->options['prautoblogger_migrated_remove_cloudflare_v0100'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Runware user: provider + model untouched; flag set.
|
||||
*/
|
||||
public function test_runware_user_preserved(): void {
|
||||
$this->options = [
|
||||
'prautoblogger_image_provider' => 'runware',
|
||||
'prautoblogger_image_model' => 'runware:101@1',
|
||||
];
|
||||
|
||||
\PRAutoBlogger_Migrate_Remove_Cloudflare_V0100::run();
|
||||
|
||||
$this->assertSame( 'runware', $this->options['prautoblogger_image_provider'] );
|
||||
$this->assertSame( 'runware:101@1', $this->options['prautoblogger_image_model'] );
|
||||
$this->assertSame( '1', $this->options['prautoblogger_migrated_remove_cloudflare_v0100'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy slug detection — the pre-registry `flux-1-schnell` model id
|
||||
* still gets migrated even when the provider option is empty.
|
||||
*/
|
||||
public function test_legacy_slug_triggers_migration(): void {
|
||||
$this->options = [
|
||||
'prautoblogger_image_provider' => '', // Unset before v0.9.0 landed.
|
||||
'prautoblogger_image_model' => 'flux-1-schnell',
|
||||
];
|
||||
|
||||
\PRAutoBlogger_Migrate_Remove_Cloudflare_V0100::run();
|
||||
|
||||
$this->assertSame( 'runware', $this->options['prautoblogger_image_provider'] );
|
||||
$this->assertSame( 'runware:100@1', $this->options['prautoblogger_image_model'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Running the migration twice is idempotent — the second pass must
|
||||
* return immediately and must not clobber a user change made after
|
||||
* the first migration run.
|
||||
*/
|
||||
public function test_idempotent_second_run_is_noop(): void {
|
||||
$this->options = [
|
||||
'prautoblogger_image_provider' => 'cloudflare',
|
||||
'prautoblogger_image_model' => 'flux-1-schnell',
|
||||
];
|
||||
|
||||
\PRAutoBlogger_Migrate_Remove_Cloudflare_V0100::run();
|
||||
$this->assertSame( 'runware', $this->options['prautoblogger_image_provider'] );
|
||||
|
||||
// Simulate admin manually switching to OpenRouter after migration.
|
||||
$this->options['prautoblogger_image_provider'] = 'openrouter';
|
||||
$this->options['prautoblogger_image_model'] = 'google/gemini-3.1-flash-image-preview';
|
||||
|
||||
\PRAutoBlogger_Migrate_Remove_Cloudflare_V0100::run();
|
||||
|
||||
// Second run must NOT overwrite the admin's manual choice.
|
||||
$this->assertSame( 'openrouter', $this->options['prautoblogger_image_provider'] );
|
||||
$this->assertSame( 'google/gemini-3.1-flash-image-preview', $this->options['prautoblogger_image_model'] );
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user