validate( $this->validPackage() ); self::assertTrue( $result->isValid() ); self::assertSame( array(), $result->errors() ); } public function test_it_rejects_missing_required_fields(): void { $package = $this->validPackage(); unset( $package['records'] ); $result = ( new PackageValidator() )->validate( $package ); self::assertFalse( $result->isValid() ); self::assertSame( array( 'records is required.' ), $result->errors() ); } public function test_it_rejects_unsupported_schema_versions(): void { $package = $this->validPackage(); $package['schema_version'] = '2.0'; $result = ( new PackageValidator() )->validate( $package ); self::assertFalse( $result->isValid() ); self::assertSame( array( 'schema_version must be 1.0.' ), $result->errors() ); } public function test_it_rejects_missing_record_buckets(): void { $package = $this->validPackage(); unset( $package['records']['media'] ); $result = ( new PackageValidator() )->validate( $package ); self::assertFalse( $result->isValid() ); self::assertSame( array( 'records.media is required and must be an array.' ), $result->errors() ); } public function test_it_rejects_manifest_counts_that_do_not_match_records(): void { $package = $this->validPackage(); $package['manifest']['posts'] = 2; $result = ( new PackageValidator() )->validate( $package ); self::assertFalse( $result->isValid() ); self::assertSame( array( 'manifest.posts must match records.posts count.' ), $result->errors() ); } public function test_it_rejects_invalid_record_checksums(): void { $package = $this->validPackage(); $package['checksums']['records'] = 'sha256:wrong'; $result = ( new PackageValidator() )->validate( $package ); self::assertFalse( $result->isValid() ); self::assertSame( array( 'checksums.records does not match records payload.' ), $result->errors() ); } /** * @return array */ private function validPackage(): array { return array( 'schema_version' => '1.0', 'generated_at' => '2026-04-26T20:30:00+00:00', 'source' => array( 'site_url' => 'https://example.test', 'name' => 'Example Production', ), 'destination' => array( 'site_url' => 'https://staging.example.test', 'name' => 'Example Staging', ), 'manifest' => array( 'posts' => 1, 'terms' => 0, 'media' => 0, 'custom_post_types' => 0, ), 'records' => array( 'posts' => array( array( 'id' => 123, 'type' => 'post', ), ), 'terms' => array(), 'media' => array(), 'custom_post_types' => array(), ), 'checksums' => array( 'records' => PackageChecksum::records( array( 'posts' => array( array( 'id' => 123, 'type' => 'post', ), ), 'terms' => array(), 'media' => array(), 'custom_post_types' => array(), ) ), ), ); } }