feat: Pipeline Settings M2 — decompose Content/AI Models/Sources into per-step panels + Global Content Context (#172, v0.24.0)
Relocates Content/AI Models/Sources fields into the per-step Pipeline panels; adds a Global Content Context block; retires the 3 duplicate Settings tabs. Option keys unchanged (no migration). QA APPROVE for 80d8e5f; CI green. Agent-Session: pipeline-settings-m2-merge
This commit is contained in:
214
tests/unit/Admin/PipelineSettingsOptionFieldsTest.php
Normal file
214
tests/unit/Admin/PipelineSettingsOptionFieldsTest.php
Normal file
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
/**
|
||||
* Unit tests for PRAutoBlogger_Pipeline_Settings_Option_Fields (and _Data).
|
||||
*
|
||||
* Locks the contracts for:
|
||||
* (1) Allowlist completeness — every context yields at least one field; no duplicates.
|
||||
* (2) sanitize_option() per type — textarea, select, number, toggle, checkboxes.
|
||||
* (3) select out-of-range falls back to default.
|
||||
* (4) number bounds clamping.
|
||||
* (5) checkboxes unknown values are filtered out.
|
||||
* (6) Field type assertions per context.
|
||||
*
|
||||
* Save-handler integration tests are in PipelineSettingsStepSaveTest.php.
|
||||
*
|
||||
* @see admin/class-pipeline-settings-option-fields.php
|
||||
* @see admin/class-pipeline-settings-option-fields-data.php
|
||||
*
|
||||
* @package PRAutoBlogger\Tests\Admin
|
||||
*/
|
||||
|
||||
namespace PRAutoBlogger\Tests\Admin;
|
||||
|
||||
use PRAutoBlogger\Tests\BaseTestCase;
|
||||
use Brain\Monkey\Functions;
|
||||
|
||||
class PipelineSettingsOptionFieldsTest extends BaseTestCase {
|
||||
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
Functions\when( 'sanitize_key' )->alias(
|
||||
static function ( $val ) {
|
||||
return preg_replace( '/[^a-z0-9_\-]/', '', strtolower( (string) $val ) );
|
||||
}
|
||||
);
|
||||
Functions\when( 'sanitize_text_field' )->alias(
|
||||
static function ( $val ) { return trim( (string) $val ); }
|
||||
);
|
||||
Functions\when( 'sanitize_textarea_field' )->alias(
|
||||
static function ( $val ) { return trim( strip_tags( (string) $val ) ); }
|
||||
);
|
||||
Functions\when( 'absint' )->alias(
|
||||
static function ( $val ) { return abs( (int) $val ); }
|
||||
);
|
||||
Functions\when( 'wp_json_encode' )->alias( 'json_encode' );
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// § CONTEXTS AND ALLOWLIST
|
||||
// =========================================================================
|
||||
|
||||
public function test_every_context_yields_fields(): void {
|
||||
foreach ( \PRAutoBlogger_Pipeline_Settings_Option_Fields::contexts() as $ctx ) {
|
||||
$fields = \PRAutoBlogger_Pipeline_Settings_Option_Fields::get_fields_for_context( $ctx );
|
||||
$this->assertNotEmpty( $fields, "Context '$ctx' returned no fields." );
|
||||
}
|
||||
}
|
||||
|
||||
public function test_unknown_context_returns_empty(): void {
|
||||
$fields = \PRAutoBlogger_Pipeline_Settings_Option_Fields::get_fields_for_context( 'nonexistent' );
|
||||
$this->assertSame( array(), $fields );
|
||||
}
|
||||
|
||||
public function test_allowed_options_no_duplicates(): void {
|
||||
$opts = \PRAutoBlogger_Pipeline_Settings_Option_Fields::allowed_options();
|
||||
$unique = array_unique( $opts );
|
||||
$this->assertCount( count( $unique ), $opts, 'Duplicate option names found.' );
|
||||
}
|
||||
|
||||
public function test_allowlist_contains_all_expected_keys(): void {
|
||||
$opts = \PRAutoBlogger_Pipeline_Settings_Option_Fields::allowed_options();
|
||||
foreach ( array(
|
||||
'prautoblogger_niche_description',
|
||||
'prautoblogger_enabled_sources',
|
||||
'prautoblogger_research_prompt',
|
||||
'prautoblogger_analysis_instructions',
|
||||
'prautoblogger_topic_exclusions',
|
||||
'prautoblogger_writing_pipeline',
|
||||
'prautoblogger_tone',
|
||||
'prautoblogger_min_word_count',
|
||||
'prautoblogger_max_word_count',
|
||||
'prautoblogger_reasoning_enabled',
|
||||
'prautoblogger_reasoning_effort',
|
||||
'prautoblogger_editor_instructions',
|
||||
) as $key ) {
|
||||
$this->assertContains( $key, $opts, "Key '$key' missing from allowlist." );
|
||||
}
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// § SANITIZE — textarea
|
||||
// =========================================================================
|
||||
|
||||
public function test_sanitize_textarea_strips_tags(): void {
|
||||
$field = array( 'type' => 'textarea' );
|
||||
$result = \PRAutoBlogger_Pipeline_Settings_Option_Fields::sanitize_option( '<b>hello</b>', $field );
|
||||
$this->assertSame( 'hello', $result );
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// § SANITIZE — toggle
|
||||
// =========================================================================
|
||||
|
||||
public function test_sanitize_toggle_one_returns_one(): void {
|
||||
$field = array( 'type' => 'toggle' );
|
||||
$this->assertSame( '1', \PRAutoBlogger_Pipeline_Settings_Option_Fields::sanitize_option( '1', $field ) );
|
||||
}
|
||||
|
||||
public function test_sanitize_toggle_non_one_returns_zero(): void {
|
||||
$field = array( 'type' => 'toggle' );
|
||||
$this->assertSame( '0', \PRAutoBlogger_Pipeline_Settings_Option_Fields::sanitize_option( 'yes', $field ) );
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// § SANITIZE — number
|
||||
// =========================================================================
|
||||
|
||||
public function test_sanitize_number_clamps_below_min(): void {
|
||||
$field = array( 'type' => 'number', 'min' => 200 );
|
||||
$this->assertSame( 200, \PRAutoBlogger_Pipeline_Settings_Option_Fields::sanitize_option( 50, $field ) );
|
||||
}
|
||||
|
||||
public function test_sanitize_number_clamps_above_max(): void {
|
||||
$field = array( 'type' => 'number', 'min' => 1, 'max' => 72 );
|
||||
$this->assertSame( 72, \PRAutoBlogger_Pipeline_Settings_Option_Fields::sanitize_option( 100, $field ) );
|
||||
}
|
||||
|
||||
public function test_sanitize_number_valid_value_unchanged(): void {
|
||||
$field = array( 'type' => 'number', 'min' => 5, 'max' => 100 );
|
||||
$this->assertSame( 25, \PRAutoBlogger_Pipeline_Settings_Option_Fields::sanitize_option( 25, $field ) );
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// § SANITIZE — select
|
||||
// =========================================================================
|
||||
|
||||
public function test_sanitize_select_valid_value_accepted(): void {
|
||||
$field = array(
|
||||
'type' => 'select',
|
||||
'default' => 'day',
|
||||
'options' => array( 'day' => 'Day', 'week' => 'Week', 'month' => 'Month' ),
|
||||
);
|
||||
$this->assertSame( 'week', \PRAutoBlogger_Pipeline_Settings_Option_Fields::sanitize_option( 'week', $field ) );
|
||||
}
|
||||
|
||||
public function test_sanitize_select_invalid_falls_back_to_default(): void {
|
||||
$field = array(
|
||||
'type' => 'select',
|
||||
'default' => 'day',
|
||||
'options' => array( 'day' => 'Day', 'week' => 'Week' ),
|
||||
);
|
||||
$this->assertSame( 'day', \PRAutoBlogger_Pipeline_Settings_Option_Fields::sanitize_option( 'evil', $field ) );
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// § SANITIZE — checkboxes
|
||||
// =========================================================================
|
||||
|
||||
public function test_sanitize_checkboxes_filters_unknown_values(): void {
|
||||
$field = array(
|
||||
'type' => 'checkboxes',
|
||||
'choices' => array( 'reddit' => 'Reddit', 'llm_research' => 'LLM' ),
|
||||
);
|
||||
$result = \PRAutoBlogger_Pipeline_Settings_Option_Fields::sanitize_option( array( 'reddit', 'evil' ), $field );
|
||||
$decoded = json_decode( $result, true );
|
||||
$this->assertSame( array( 'reddit' ), $decoded );
|
||||
}
|
||||
|
||||
public function test_sanitize_checkboxes_non_array_returns_json_empty(): void {
|
||||
$field = array(
|
||||
'type' => 'checkboxes',
|
||||
'choices' => array( 'reddit' => 'Reddit' ),
|
||||
);
|
||||
$result = \PRAutoBlogger_Pipeline_Settings_Option_Fields::sanitize_option( 'reddit', $field );
|
||||
$this->assertSame( '[]', $result );
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// § FIELD TYPE ASSERTIONS PER CONTEXT
|
||||
// =========================================================================
|
||||
|
||||
public function test_writer_context_reasoning_enabled_is_toggle(): void {
|
||||
$fields = \PRAutoBlogger_Pipeline_Settings_Option_Fields::get_fields_for_context( 'writer' );
|
||||
foreach ( $fields as $f ) {
|
||||
if ( 'prautoblogger_reasoning_enabled' === $f['id'] ) {
|
||||
$this->assertSame( 'toggle', $f['type'] );
|
||||
return;
|
||||
}
|
||||
}
|
||||
$this->fail( 'prautoblogger_reasoning_enabled not found in writer context.' );
|
||||
}
|
||||
|
||||
public function test_research_context_enabled_sources_is_checkboxes(): void {
|
||||
$fields = \PRAutoBlogger_Pipeline_Settings_Option_Fields::get_fields_for_context( 'research' );
|
||||
foreach ( $fields as $f ) {
|
||||
if ( 'prautoblogger_enabled_sources' === $f['id'] ) {
|
||||
$this->assertSame( 'checkboxes', $f['type'] );
|
||||
return;
|
||||
}
|
||||
}
|
||||
$this->fail( 'prautoblogger_enabled_sources not found in research context.' );
|
||||
}
|
||||
|
||||
public function test_writer_context_tone_is_select_with_five_options(): void {
|
||||
$fields = \PRAutoBlogger_Pipeline_Settings_Option_Fields::get_fields_for_context( 'writer' );
|
||||
foreach ( $fields as $f ) {
|
||||
if ( 'prautoblogger_tone' === $f['id'] ) {
|
||||
$this->assertSame( 'select', $f['type'] );
|
||||
$this->assertCount( 5, $f['options'] );
|
||||
return;
|
||||
}
|
||||
}
|
||||
$this->fail( 'prautoblogger_tone not found in writer context.' );
|
||||
}
|
||||
}
|
||||
294
tests/unit/Admin/PipelineSettingsStepSaveTest.php
Normal file
294
tests/unit/Admin/PipelineSettingsStepSaveTest.php
Normal file
@@ -0,0 +1,294 @@
|
||||
<?php
|
||||
/**
|
||||
* Integration tests for save_step_settings action in the Pipeline Settings save handler.
|
||||
*
|
||||
* Covers:
|
||||
* (1) Unknown step_context is rejected before any update_option().
|
||||
* (2) Valid contexts (global, analysis, editorial, writer) persist the right options.
|
||||
* (3) Failed nonce prevents saves.
|
||||
* (4) Insufficient capability prevents saves.
|
||||
* (5) Missing nonce field returns idle (not error).
|
||||
*
|
||||
* @see admin/class-pipeline-settings-save-handler.php
|
||||
* @see admin/class-pipeline-settings-option-fields.php
|
||||
*
|
||||
* @package PRAutoBlogger\Tests\Admin
|
||||
*/
|
||||
|
||||
namespace PRAutoBlogger\Tests\Admin;
|
||||
|
||||
use PRAutoBlogger\Tests\BaseTestCase;
|
||||
use Brain\Monkey\Functions;
|
||||
|
||||
class PipelineSettingsStepSaveTest extends BaseTestCase {
|
||||
|
||||
/** @var array<string, mixed> Captured update_option() calls. */
|
||||
private array $saved_options = array();
|
||||
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$_SERVER['REQUEST_METHOD'] = 'POST';
|
||||
$_POST = array();
|
||||
|
||||
Functions\when( 'wp_verify_nonce' )->justReturn( true );
|
||||
Functions\when( 'wp_unslash' )->returnArg();
|
||||
Functions\when( 'sanitize_key' )->alias(
|
||||
static function ( $val ) {
|
||||
return preg_replace( '/[^a-z0-9_\-]/', '', strtolower( (string) $val ) );
|
||||
}
|
||||
);
|
||||
Functions\when( 'sanitize_text_field' )->alias(
|
||||
static function ( $val ) { return trim( (string) $val ); }
|
||||
);
|
||||
Functions\when( 'sanitize_textarea_field' )->alias(
|
||||
static function ( $val ) { return trim( strip_tags( (string) $val ) ); }
|
||||
);
|
||||
Functions\when( 'absint' )->alias(
|
||||
static function ( $val ) { return abs( (int) $val ); }
|
||||
);
|
||||
Functions\when( 'wp_json_encode' )->alias( 'json_encode' );
|
||||
Functions\when( 'current_user_can' )->justReturn( true );
|
||||
Functions\when( 'esc_html' )->alias(
|
||||
static function ( $v ) { return htmlspecialchars( (string) $v, ENT_QUOTES ); }
|
||||
);
|
||||
Functions\when( 'update_option' )->alias(
|
||||
function ( $name, $value ) {
|
||||
$this->saved_options[ $name ] = $value;
|
||||
return true;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
protected function tearDown(): void {
|
||||
$_POST = array();
|
||||
$_SERVER['REQUEST_METHOD'] = 'GET';
|
||||
$this->saved_options = array();
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// § CONTEXT VALIDATION
|
||||
// =========================================================================
|
||||
|
||||
public function test_unknown_context_returns_error_and_no_saves(): void {
|
||||
$_POST = array(
|
||||
\PRAutoBlogger_Pipeline_Settings_Page::NONCE_FIELD => 'valid',
|
||||
'pipeline_action' => 'save_step_settings',
|
||||
'step_context' => 'bad_context',
|
||||
);
|
||||
|
||||
$result = \PRAutoBlogger_Pipeline_Settings_Save_Handler::maybe_process_save();
|
||||
|
||||
$this->assertSame( 'error', $result['status'] );
|
||||
$this->assertEmpty( $this->saved_options );
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// § GLOBAL CONTEXT
|
||||
// =========================================================================
|
||||
|
||||
public function test_global_context_saves_niche_description(): void {
|
||||
$_POST = array(
|
||||
\PRAutoBlogger_Pipeline_Settings_Page::NONCE_FIELD => 'valid',
|
||||
'pipeline_action' => 'save_step_settings',
|
||||
'step_context' => 'global',
|
||||
'prautoblogger_niche_description' => 'Peptides and biohacking',
|
||||
);
|
||||
|
||||
$result = \PRAutoBlogger_Pipeline_Settings_Save_Handler::maybe_process_save();
|
||||
|
||||
$this->assertSame( 'saved', $result['status'] );
|
||||
$this->assertSame( 'Peptides and biohacking', $this->saved_options['prautoblogger_niche_description'] );
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// § ANALYSIS CONTEXT
|
||||
// =========================================================================
|
||||
|
||||
public function test_analysis_context_saves_both_fields(): void {
|
||||
$_POST = array(
|
||||
\PRAutoBlogger_Pipeline_Settings_Page::NONCE_FIELD => 'valid',
|
||||
'pipeline_action' => 'save_step_settings',
|
||||
'step_context' => 'analysis',
|
||||
'prautoblogger_analysis_instructions' => 'Focus on safety topics.',
|
||||
'prautoblogger_topic_exclusions' => 'politics, religion',
|
||||
);
|
||||
|
||||
$result = \PRAutoBlogger_Pipeline_Settings_Save_Handler::maybe_process_save();
|
||||
|
||||
$this->assertSame( 'saved', $result['status'] );
|
||||
$this->assertArrayHasKey( 'prautoblogger_analysis_instructions', $this->saved_options );
|
||||
$this->assertArrayHasKey( 'prautoblogger_topic_exclusions', $this->saved_options );
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// § EDITORIAL CONTEXT
|
||||
// =========================================================================
|
||||
|
||||
public function test_editorial_context_saves_editor_instructions(): void {
|
||||
$_POST = array(
|
||||
\PRAutoBlogger_Pipeline_Settings_Page::NONCE_FIELD => 'valid',
|
||||
'pipeline_action' => 'save_step_settings',
|
||||
'step_context' => 'editorial',
|
||||
'prautoblogger_editor_instructions' => 'Be strict about disclaimers.',
|
||||
);
|
||||
|
||||
$result = \PRAutoBlogger_Pipeline_Settings_Save_Handler::maybe_process_save();
|
||||
|
||||
$this->assertSame( 'saved', $result['status'] );
|
||||
$this->assertSame( 'Be strict about disclaimers.', $this->saved_options['prautoblogger_editor_instructions'] );
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// § WRITER CONTEXT
|
||||
// =========================================================================
|
||||
|
||||
public function test_writer_context_saves_tone_and_pipeline(): void {
|
||||
$_POST = array(
|
||||
\PRAutoBlogger_Pipeline_Settings_Page::NONCE_FIELD => 'valid',
|
||||
'pipeline_action' => 'save_step_settings',
|
||||
'step_context' => 'writer',
|
||||
'prautoblogger_tone' => 'authoritative',
|
||||
'prautoblogger_writing_pipeline' => 'single_pass',
|
||||
'prautoblogger_min_word_count' => '600',
|
||||
'prautoblogger_max_word_count' => '1800',
|
||||
'prautoblogger_reasoning_enabled' => '0',
|
||||
'prautoblogger_reasoning_effort' => 'medium',
|
||||
);
|
||||
|
||||
$result = \PRAutoBlogger_Pipeline_Settings_Save_Handler::maybe_process_save();
|
||||
|
||||
$this->assertSame( 'saved', $result['status'] );
|
||||
$this->assertSame( 'authoritative', $this->saved_options['prautoblogger_tone'] );
|
||||
$this->assertSame( 'single_pass', $this->saved_options['prautoblogger_writing_pipeline'] );
|
||||
}
|
||||
|
||||
public function test_writer_context_number_fields_are_integers(): void {
|
||||
$_POST = array(
|
||||
\PRAutoBlogger_Pipeline_Settings_Page::NONCE_FIELD => 'valid',
|
||||
'pipeline_action' => 'save_step_settings',
|
||||
'step_context' => 'writer',
|
||||
'prautoblogger_tone' => 'informational',
|
||||
'prautoblogger_writing_pipeline' => 'multi_step',
|
||||
'prautoblogger_min_word_count' => '1000',
|
||||
'prautoblogger_max_word_count' => '2500',
|
||||
'prautoblogger_reasoning_enabled' => '0',
|
||||
'prautoblogger_reasoning_effort' => 'medium',
|
||||
);
|
||||
|
||||
$result = \PRAutoBlogger_Pipeline_Settings_Save_Handler::maybe_process_save();
|
||||
|
||||
$this->assertSame( 'saved', $result['status'] );
|
||||
$this->assertIsInt( $this->saved_options['prautoblogger_min_word_count'] );
|
||||
$this->assertIsInt( $this->saved_options['prautoblogger_max_word_count'] );
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// § SECURITY GATES
|
||||
// =========================================================================
|
||||
|
||||
public function test_invalid_nonce_prevents_save(): void {
|
||||
Functions\when( 'wp_verify_nonce' )->justReturn( false );
|
||||
|
||||
$_POST = array(
|
||||
\PRAutoBlogger_Pipeline_Settings_Page::NONCE_FIELD => 'bad',
|
||||
'pipeline_action' => 'save_step_settings',
|
||||
'step_context' => 'global',
|
||||
'prautoblogger_niche_description' => 'Should not save.',
|
||||
);
|
||||
|
||||
$result = \PRAutoBlogger_Pipeline_Settings_Save_Handler::maybe_process_save();
|
||||
|
||||
$this->assertSame( 'error', $result['status'] );
|
||||
$this->assertEmpty( $this->saved_options );
|
||||
}
|
||||
|
||||
public function test_insufficient_capability_prevents_save(): void {
|
||||
Functions\when( 'current_user_can' )->justReturn( false );
|
||||
|
||||
$_POST = array(
|
||||
\PRAutoBlogger_Pipeline_Settings_Page::NONCE_FIELD => 'valid',
|
||||
'pipeline_action' => 'save_step_settings',
|
||||
'step_context' => 'global',
|
||||
);
|
||||
|
||||
$result = \PRAutoBlogger_Pipeline_Settings_Save_Handler::maybe_process_save();
|
||||
|
||||
$this->assertSame( 'error', $result['status'] );
|
||||
$this->assertEmpty( $this->saved_options );
|
||||
}
|
||||
|
||||
public function test_missing_nonce_field_returns_idle(): void {
|
||||
$_POST = array(
|
||||
'pipeline_action' => 'save_step_settings',
|
||||
'step_context' => 'global',
|
||||
);
|
||||
|
||||
$result = \PRAutoBlogger_Pipeline_Settings_Save_Handler::maybe_process_save();
|
||||
|
||||
$this->assertSame( 'idle', $result['status'] );
|
||||
$this->assertEmpty( $this->saved_options );
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// § RESEARCH CONTEXT
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* The research context is the only step context containing a `checkboxes`-type
|
||||
* field (prautoblogger_enabled_sources). Its save path is distinct: the POST
|
||||
* value is an array → each item sanitize_key'd → filtered against the choices
|
||||
* allowlist → JSON-encoded string persisted via update_option().
|
||||
*
|
||||
* This test exercises the full integration path for that field and asserts
|
||||
* that an unknown source key is stripped and only allowlisted keys survive.
|
||||
*/
|
||||
public function test_research_context_saves_source_settings(): void {
|
||||
$_POST = array(
|
||||
\PRAutoBlogger_Pipeline_Settings_Page::NONCE_FIELD => 'valid',
|
||||
'pipeline_action' => 'save_step_settings',
|
||||
'step_context' => 'research',
|
||||
'prautoblogger_enabled_sources' => array( 'reddit' ),
|
||||
'prautoblogger_target_subreddits' => 'peptides, Nootropics',
|
||||
'prautoblogger_reddit_time_filter' => 'week',
|
||||
'prautoblogger_reddit_posts_per_subreddit' => '20',
|
||||
'prautoblogger_pullpush_cache_ttl' => '12',
|
||||
'prautoblogger_research_prompt' => 'Find trending topics in {niche}.',
|
||||
);
|
||||
|
||||
$result = \PRAutoBlogger_Pipeline_Settings_Save_Handler::maybe_process_save();
|
||||
|
||||
$this->assertSame( 'saved', $result['status'] );
|
||||
$decoded = json_decode( $this->saved_options['prautoblogger_enabled_sources'], true );
|
||||
$this->assertSame( array( 'reddit' ), $decoded );
|
||||
$this->assertSame( 'week', $this->saved_options['prautoblogger_reddit_time_filter'] );
|
||||
$this->assertIsInt( $this->saved_options['prautoblogger_reddit_posts_per_subreddit'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Unknown source keys supplied in the checkboxes array must be stripped —
|
||||
* only values present in the field's `choices` allowlist survive.
|
||||
*/
|
||||
public function test_research_context_checkboxes_filters_unknown_sources(): void {
|
||||
$_POST = array(
|
||||
\PRAutoBlogger_Pipeline_Settings_Page::NONCE_FIELD => 'valid',
|
||||
'pipeline_action' => 'save_step_settings',
|
||||
'step_context' => 'research',
|
||||
'prautoblogger_enabled_sources' => array( 'reddit', 'unknown_source', 'llm_research' ),
|
||||
'prautoblogger_target_subreddits' => '',
|
||||
'prautoblogger_reddit_time_filter' => 'day',
|
||||
'prautoblogger_reddit_posts_per_subreddit' => '25',
|
||||
'prautoblogger_pullpush_cache_ttl' => '6',
|
||||
'prautoblogger_research_prompt' => '',
|
||||
);
|
||||
|
||||
$result = \PRAutoBlogger_Pipeline_Settings_Save_Handler::maybe_process_save();
|
||||
|
||||
$this->assertSame( 'saved', $result['status'] );
|
||||
$decoded = json_decode( $this->saved_options['prautoblogger_enabled_sources'], true );
|
||||
$this->assertContains( 'reddit', $decoded );
|
||||
$this->assertContains( 'llm_research', $decoded );
|
||||
$this->assertNotContains( 'unknown_source', $decoded );
|
||||
}
|
||||
}
|
||||
@@ -28,19 +28,21 @@ class SettingsFieldsExtendedTest extends BaseTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* get_fields() must return exactly 29 fields (18 local + 11 image).
|
||||
* get_fields() must return exactly 25 fields (14 local + 11 image).
|
||||
*
|
||||
* This pins the array_merge fix: if a + operator re-appears the image
|
||||
* fields are silently dropped to 18 and this test fails CI.
|
||||
* Count breakdown: 18 schedule/publishing/analytics/display/sources fields
|
||||
* M2: 4 fields removed (reasoning_enabled, reasoning_effort from AI Models;
|
||||
* research_model, research_prompt from Sources) — now owned by Pipeline Settings.
|
||||
* This pins the array_merge fix: if a + operator re-appears the image fields
|
||||
* are silently dropped to 14 and this test fails CI.
|
||||
* Count breakdown: 14 schedule/publishing/analytics/display fields
|
||||
* from the local array + 11 image fields from Settings_Fields_Images.
|
||||
*/
|
||||
public function test_get_fields_returns_29_fields(): void {
|
||||
public function test_get_fields_returns_25_fields(): void {
|
||||
$fields = \PRAutoBlogger_Settings_Fields_Extended::get_fields();
|
||||
$this->assertCount(
|
||||
29,
|
||||
25,
|
||||
$fields,
|
||||
'Expected 29 fields (18 local + 11 image). A + union instead of array_merge would return only 18.'
|
||||
'Expected 25 fields (14 local + 11 image). M2 retired AI Models + Sources from Extended.'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user