Files
peptide-repo-core/tests/unit/Migration0004Test.php
peptiderepo 8d3064785c fix: resolve all PHPCS violations and 300-line rule breaches
- Add @package Peptide_Repo_Core file docblocks to all PHP files
- Add @var docblocks to all public readonly DTO properties
- Add @param docs to sanitize_evidence_strength / sanitize_review_status
- Replace short ternary ?: with phpcs:ignore on each violating line
- Add phpcs:ignore for InterpolatedNotPrepared on ${table} SQL strings
- Add phpcs:ignore for GlobalVariablesOverride in uninstall.php and card.php
- Add translators comment to __ call with placeholder in related-posts-section
- Fix InlineComment.InvalidEndChar: add periods to all bare inline comments
- Expand single-line /** @return void */ docblocks with summaries
- SPLIT class-pr-core-seed-data.php (was 360 lines):
  → class-pr-core-seed-data.php (149 lines, orchestration only)
  → class-pr-core-seed-fixtures.php (254 lines, static fixture data)
- SPLIT class-pr-core-peptide-cpt.php (was 309 lines):
  → class-pr-core-peptide-cpt.php (224 lines, CPT + hooks + sanitizers)
  → class-pr-core-peptide-meta-schema.php (133 lines, meta field defs)
- SPLIT class-pr-core-settings.php (was 340 lines after docblock expansion):
  → class-pr-core-settings.php (264 lines, registration + sanitization)
  → class-pr-core-settings-renderer.php (124 lines, render methods)
- All includes/ PHP files now <= 300 lines

Agent-Session: claude-adopt-ci-20260616
2026-06-16 15:48:53 +00:00

240 lines
10 KiB
PHP

<?php
/**
* Unit tests for PR_Core_Migration_0004_Backfill_Peptide_Meta.
*
* Ported from tests/unit/test-migration-0004.php.
*
* Coverage:
* - parse_weight(): strips "Da"/"DA"/"da" suffix, handles plain float,
* empty string → 0.0, suffix-only → 0.0.
* - parse_aliases_string(): splits CSV, trims, drops empty, returns '[]' for empty.
* - PR_Core_Schema_Sanitizers::sanitize_molecular_formula(): valid, HTML, groups,
* injection, fully-invalid, empty.
* - Idempotency: backfill_post() returns 'skipped' when all three keys populated.
* - PSA source path: copies and transforms psa_* → _pr_* keys.
* - PubChem skip path: 'pubchem_skip' when PubChem network fails.
*
* @package PeptideRepoCore\Tests
*/
use PHPUnit\Framework\TestCase;
/**
* Tests for PR_Core_Migration_0004_Backfill_Peptide_Meta.
*/
class Migration0004Test extends TestCase {
/** @var PR_Core_Migration_0004_Backfill_Peptide_Meta */
private $migration;
protected function setUp(): void {
$GLOBALS['pr_test_postmeta'] = [];
$GLOBALS['pr_test_updated_meta'] = [];
$GLOBALS['pr_test_posts'] = [];
$GLOBALS['pr_core_test_state'] = [
'existing_post_types' => [],
'existing_taxonomies' => [],
'registered_post_types' => [],
'registered_taxonomies' => [],
'registered_meta' => [],
'added_actions' => [],
'added_filters' => [],
];
require_once PR_CORE_PLUGIN_DIR . 'includes/cpt/class-pr-core-schema-sanitizers.php';
require_once PR_CORE_PLUGIN_DIR . 'includes/cpt/class-pr-core-peptide-cpt.php';
require_once PR_CORE_PLUGIN_DIR . 'includes/migrations/class-pr-core-pubchem-client.php';
require_once PR_CORE_PLUGIN_DIR . 'includes/migrations/class-pr-core-migration-0004-backfill-peptide-meta.php';
$this->migration = new PR_Core_Migration_0004_Backfill_Peptide_Meta();
}
// ── Helper: call private method via reflection ────────────────────.
/**
* @param mixed[] $args
* @return mixed
*/
private function call_private( object $obj, string $method, array $args = [] ) {
$ref = new ReflectionMethod( $obj, $method );
$ref->setAccessible( true );
return $ref->invokeArgs( $obj, $args );
}
// ── parse_weight() ────────────────────────────────────────────────.
public function test_parse_weight_strips_da_suffix(): void {
$this->assertSame( 1419.5, $this->call_private( $this->migration, 'parse_weight', [ '1419.5 Da' ] ) );
}
public function test_parse_weight_strips_uppercase_da(): void {
$this->assertSame( 1419.5, $this->call_private( $this->migration, 'parse_weight', [ '1419.5 DA' ] ) );
}
public function test_parse_weight_plain_float(): void {
$this->assertSame( 1419.5, $this->call_private( $this->migration, 'parse_weight', [ '1419.5' ] ) );
}
public function test_parse_weight_empty_returns_zero(): void {
$this->assertSame( 0.0, $this->call_private( $this->migration, 'parse_weight', [ '' ] ) );
}
public function test_parse_weight_suffix_only_returns_zero(): void {
$this->assertSame( 0.0, $this->call_private( $this->migration, 'parse_weight', [ ' Da ' ] ) );
}
public function test_parse_weight_lowercase_da_with_whitespace(): void {
$this->assertSame( 800.123, $this->call_private( $this->migration, 'parse_weight', [ ' 800.123 da ' ] ) );
}
// ── parse_aliases_string() ────────────────────────────────────────.
public function test_parse_aliases_string_splits_csv(): void {
$result = json_decode(
$this->call_private( $this->migration, 'parse_aliases_string', [ 'Body Protection Compound-157, PL 14736, PL-10, Bepecin' ] ),
true
);
$this->assertIsArray( $result );
$this->assertCount( 4, $result );
$this->assertSame( 'Body Protection Compound-157', $result[0] );
$this->assertSame( 'PL 14736', $result[1] );
}
public function test_parse_aliases_string_empty_returns_json_empty_array(): void {
$this->assertSame( '[]', $this->call_private( $this->migration, 'parse_aliases_string', [ '' ] ) );
}
public function test_parse_aliases_string_whitespace_only_returns_json_empty_array(): void {
$this->assertSame( '[]', $this->call_private( $this->migration, 'parse_aliases_string', [ ' , , ' ] ) );
}
public function test_parse_aliases_string_single_alias(): void {
$result = json_decode( $this->call_private( $this->migration, 'parse_aliases_string', [ 'Only One' ] ), true );
$this->assertCount( 1, $result );
}
// ── sanitize_molecular_formula() ──────────────────────────────────.
public function test_sanitize_formula_valid_passes_unchanged(): void {
$this->assertSame( 'C62H98N16O22', PR_Core_Schema_Sanitizers::sanitize_molecular_formula( 'C62H98N16O22' ) );
}
public function test_sanitize_formula_strips_html_tags(): void {
$this->assertSame( 'C62H98N16O22', PR_Core_Schema_Sanitizers::sanitize_molecular_formula( '<b>C62H98N16O22</b>' ) );
}
public function test_sanitize_formula_preserves_parentheses(): void {
$this->assertSame( 'C2H5(OH)', PR_Core_Schema_Sanitizers::sanitize_molecular_formula( 'C2H5(OH)' ) );
}
public function test_sanitize_formula_strips_non_formula_chars(): void {
$this->assertSame( 'C10H12', PR_Core_Schema_Sanitizers::sanitize_molecular_formula( "C10H12\ninjection" ) );
}
public function test_sanitize_formula_fully_invalid_returns_empty(): void {
$this->assertSame( '', PR_Core_Schema_Sanitizers::sanitize_molecular_formula( '<script>alert(1)</script>' ) );
}
public function test_sanitize_formula_empty_returns_empty(): void {
$this->assertSame( '', PR_Core_Schema_Sanitizers::sanitize_molecular_formula( '' ) );
}
public function test_sanitize_formula_whitespace_only_returns_empty(): void {
$this->assertSame( '', PR_Core_Schema_Sanitizers::sanitize_molecular_formula( ' ' ) );
}
// ── Idempotency ───────────────────────────────────────────────────.
public function test_backfill_post_skipped_when_all_keys_populated(): void {
$GLOBALS['pr_test_postmeta'][1] = [
'_pr_molecular_formula' => 'C62H98N16O22',
'_pr_molecular_weight' => '1419.5',
'_pr_aliases' => '["Alias One"]',
];
$result = $this->call_private( $this->migration, 'backfill_post', [ 1 ] );
$this->assertSame( 'skipped', $result );
$this->assertEmpty( $GLOBALS['pr_test_updated_meta'] );
}
// ── PSA source path ───────────────────────────────────────────────.
public function test_backfill_post_copies_psa_data(): void {
$GLOBALS['pr_test_postmeta'][2] = [
'psa_molecular_formula' => 'C62H98N16O22',
'psa_molecular_weight' => '1419.5 Da',
'psa_aliases' => 'Body Protection Compound-157, PL 14736',
];
$GLOBALS['pr_test_posts'][2] = (object) [ 'post_title' => 'BPC-157', 'ID' => 2 ];
$result = $this->call_private( $this->migration, 'backfill_post', [ 2 ] );
$this->assertSame( 'copied_psa', $result );
}
public function test_backfill_post_psa_writes_formula_correctly(): void {
$GLOBALS['pr_test_postmeta'][2] = [
'psa_molecular_formula' => 'C62H98N16O22',
'psa_molecular_weight' => '1419.5 Da',
'psa_aliases' => 'Body Protection Compound-157',
];
$GLOBALS['pr_test_posts'][2] = (object) [ 'post_title' => 'BPC-157', 'ID' => 2 ];
$this->call_private( $this->migration, 'backfill_post', [ 2 ] );
$written = null;
foreach ( $GLOBALS['pr_test_updated_meta'] as $entry ) {
if ( '_pr_molecular_formula' === $entry['key'] ) {
$written = $entry['value'];
}
}
$this->assertSame( 'C62H98N16O22', $written );
}
public function test_backfill_post_psa_strips_da_from_weight(): void {
$GLOBALS['pr_test_postmeta'][2] = [
'psa_molecular_formula' => 'C62H98N16O22',
'psa_molecular_weight' => '1419.5 Da',
'psa_aliases' => 'Body Protection Compound-157',
];
$GLOBALS['pr_test_posts'][2] = (object) [ 'post_title' => 'BPC-157', 'ID' => 2 ];
$this->call_private( $this->migration, 'backfill_post', [ 2 ] );
$written = null;
foreach ( $GLOBALS['pr_test_updated_meta'] as $entry ) {
if ( '_pr_molecular_weight' === $entry['key'] ) {
$written = $entry['value'];
}
}
$this->assertSame( '1419.5', $written );
}
public function test_backfill_post_psa_writes_aliases_as_json_array(): void {
$GLOBALS['pr_test_postmeta'][2] = [
'psa_molecular_formula' => 'C62H98N16O22',
'psa_molecular_weight' => '1419.5 Da',
'psa_aliases' => 'Body Protection Compound-157, PL 14736',
];
$GLOBALS['pr_test_posts'][2] = (object) [ 'post_title' => 'BPC-157', 'ID' => 2 ];
$this->call_private( $this->migration, 'backfill_post', [ 2 ] );
$written = null;
foreach ( $GLOBALS['pr_test_updated_meta'] as $entry ) {
if ( '_pr_aliases' === $entry['key'] ) {
$written = $entry['value'];
}
}
$aliases = json_decode( $written, true );
$this->assertIsArray( $aliases );
$this->assertCount( 2, $aliases );
}
// ── PubChem skip path ─────────────────────────────────────────────.
public function test_backfill_post_returns_pubchem_skip_when_network_fails(): void {
$mock_pubchem = new class extends PR_Core_Pubchem_Client {
public function fetch_by_cid( string $cid ): ?array { return null; }
public function fetch_by_name( string $name ): ?array { return null; }
};
$mock_migration = new PR_Core_Migration_0004_Backfill_Peptide_Meta( $mock_pubchem );
$GLOBALS['pr_test_postmeta'][10] = [];
$GLOBALS['pr_test_posts'][10] = (object) [ 'post_title' => 'IGF-1 LR3', 'ID' => 10 ];
$result = $this->call_private( $mock_migration, 'backfill_post', [ 10 ] );
$this->assertSame( 'pubchem_skip', $result );
$this->assertEmpty( $GLOBALS['pr_test_updated_meta'] );
}
}