Files
WooNooW/tests/SchemaMigrationTest.php
Dwindi Ramadhana 396ca25be4 feat: Page Editor v1.0 - canonical schema, SSR parity, and migration
Major improvements to WooNooW Page Editor system:

Schema & Architecture:
- Canonical section schema with unified sectionSchema.ts
- Normalized feature-grid to use items (not features)
- Standardized default values across all section types
- Schema versioning with automatic migration on read

Backend (PHP):
- Enhanced PlaceholderRenderer with typed output contracts
- Added fallback behavior for empty/invalid dynamic sources
- Added caching support for post data resolution
- New SchemaMigration class for backward compatibility
- New Features class for feature flags
- Enhanced PageSSR with full style support
- Removed controller-level special-casing for related_posts

Frontend (Admin SPA):
- Updated CanvasRenderer with schema-aware transformation
- Enhanced InspectorPanel with canonical schema metadata
- Added new section renderers

Frontend (Customer SPA):
- New section components: BentoCategoryGrid, MarqueeBanner, ProductCarousel, ShoppableImage
- Updated FeatureGridSection for items prop contract

Testing:
- Add PHP tests: SchemaMigrationTest, PlaceholderRendererTest, PageSSRTest
- Add TypeScript tests: schema-integration, feature-grid-regression
- Add parity tests for React vs SSR content matching
- Add CI script: check-schema-drift.mjs
- Add VERIFICATION_CHECKLIST.md

Documentation:
- RELEASE_NOTES-v1.0.md with full release notes
- docs/PAGE_EDITOR_SECTION_SCHEMA_V1.md
- docs/PAGE_EDITOR_SSR_COVERAGE_AUDIT.md
2026-05-30 13:02:08 +07:00

207 lines
5.9 KiB
PHP

<?php
/**
* Schema Migration Tests
* Tests for backward compatibility and migration of legacy structures
*/
namespace WooNooW\Tests;
use PHPUnit\Framework\TestCase;
use WooNooW\Frontend\SchemaMigration;
class SchemaMigrationTest extends TestCase
{
/**
* Test that v1 structures don't need migration
*/
public function test_v1_structures_dont_need_migration()
{
$structure = [
'type' => 'page',
'schemaVersion' => 1,
'sections' => [],
];
$this->assertFalse(SchemaMigration::needs_migration($structure));
}
/**
* Test that structures without version need migration
*/
public function test_structures_without_version_need_migration()
{
$structure = [
'type' => 'page',
'sections' => [],
];
$this->assertTrue(SchemaMigration::needs_migration($structure));
}
/**
* Test migration of feature-grid with legacy features key
*/
public function test_migrate_feature_grid_features_to_items()
{
$structure = [
'schemaVersion' => 0,
'sections' => [
[
'type' => 'feature-grid',
'props' => [
'heading' => ['type' => 'static', 'value' => 'Test'],
'features' => [
['title' => 'Feature 1', 'description' => 'Desc 1'],
['title' => 'Feature 2', 'description' => 'Desc 2'],
],
],
],
],
];
$migrated = SchemaMigration::migrate($structure);
$this->assertEquals(1, $migrated['schemaVersion']);
$this->assertArrayHasKey('items', $migrated['sections'][0]['props']);
$this->assertEquals($structure['sections'][0]['props']['features'], $migrated['sections'][0]['props']['items']);
}
/**
* Test migration of feature-grid with empty features string
*/
public function test_migrate_feature_grid_empty_features_to_items()
{
$structure = [
'schemaVersion' => 0,
'sections' => [
[
'type' => 'feature-grid',
'props' => [
'heading' => ['type' => 'static', 'value' => 'Test'],
'features' => '',
],
],
],
];
$migrated = SchemaMigration::migrate($structure);
$this->assertEquals([], $migrated['sections'][0]['props']['items']);
}
/**
* Test migration of container_width to contentWidth
*/
public function test_migrate_container_width_to_content_width()
{
$structure = [
'schemaVersion' => 0,
'sections' => [
[
'type' => 'hero',
'styles' => [
'container_width' => 'full',
],
],
],
];
$migrated = SchemaMigration::migrate($structure);
$this->assertArrayHasKey('contentWidth', $migrated['sections'][0]['styles']);
$this->assertEquals('full', $migrated['sections'][0]['styles']['contentWidth']);
$this->assertArrayNotHasKey('container_width', $migrated['sections'][0]['styles']);
}
/**
* Test migration of background image without type
*/
public function test_migrate_background_image_adds_type()
{
$structure = [
'schemaVersion' => 0,
'sections' => [
[
'type' => 'hero',
'styles' => [
'backgroundImage' => 'https://example.com/image.jpg',
],
],
],
];
$migrated = SchemaMigration::migrate($structure);
$this->assertEquals('image', $migrated['sections'][0]['styles']['backgroundType']);
}
/**
* Test migration of height to heightPreset
*/
public function test_migrate_height_to_height_preset()
{
$structure = [
'schemaVersion' => 0,
'sections' => [
[
'type' => 'hero',
'styles' => [
'height' => 'screen',
],
],
],
];
$migrated = SchemaMigration::migrate($structure);
$this->assertArrayHasKey('heightPreset', $migrated['sections'][0]['styles']);
$this->assertEquals('fullscreen', $migrated['sections'][0]['styles']['heightPreset']);
$this->assertArrayNotHasKey('height', $migrated['sections'][0]['styles']);
}
/**
* Test migration adds default backgroundType
*/
public function test_migrate_adds_default_background_type()
{
$structure = [
'schemaVersion' => 0,
'sections' => [
[
'type' => 'hero',
'styles' => [],
],
],
];
$migrated = SchemaMigration::migrate($structure);
$this->assertEquals('solid', $migrated['sections'][0]['styles']['backgroundType']);
}
/**
* Test batch migration
*/
public function test_migrate_all()
{
$structures = [
['schemaVersion' => 0, 'sections' => []],
['schemaVersion' => 1, 'sections' => []],
['schemaVersion' => 0, 'sections' => []],
];
$migrated = SchemaMigration::migrate_all($structures);
$this->assertEquals(1, $migrated[0]['schemaVersion']);
$this->assertEquals(1, $migrated[1]['schemaVersion']);
$this->assertEquals(1, $migrated[2]['schemaVersion']);
}
/**
* Test current version is returned
*/
public function test_get_current_version()
{
$this->assertEquals(1, SchemaMigration::get_current_version());
}
}