fix: Task 6 review round 2 - builder column classes, sum check only for exact rows, unknown path wins, column structure text (S43)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
This commit is contained in:
@@ -527,6 +527,11 @@ final class AttrWriterTest extends TestCase
|
||||
self::assertSame([], $result['attrs'], $path);
|
||||
}
|
||||
|
||||
$column = ComposeFixture::attrWriter()->apply('divi/column', [], ['module.advanced.specialtyColumns' => null], 'attrs');
|
||||
self::assertStringNotContainsString('section_type', $column['errors']['attrs.module.advanced.specialtyColumns']);
|
||||
$section = ComposeFixture::attrWriter()->apply('divi/section', [], ['module.advanced.type' => null], 'attrs');
|
||||
self::assertStringContainsString('section_type', $section['errors']['attrs.module.advanced.type']);
|
||||
|
||||
$heading = ComposeFixture::attrWriter()->apply('divi/heading', [], ['module.meta.adminLabel' => ['desktop' => 'x']], 'attrs');
|
||||
self::assertSame([], $heading['errors'], 'only section type and specialty columns are structure');
|
||||
}
|
||||
|
||||
@@ -261,6 +261,20 @@ final class ComposerTest extends TestCase
|
||||
self::assertStringContainsString('label', $update['errors']['changes[0].attrs.module.meta.adminLabel']);
|
||||
}
|
||||
|
||||
/** Ruling S43: an unknown path wins over the overlap message on the same key. */
|
||||
public function testUnknownPathWinsOverOverlap(): void
|
||||
{
|
||||
$result = ComposeFixture::composer()->compose([[
|
||||
'type' => 'heading',
|
||||
'text' => 'x',
|
||||
'label' => 'B',
|
||||
'attrs' => ['module.meta' => ['desktop' => 'A']],
|
||||
]], Block::create('divi/column'), 'nodes');
|
||||
|
||||
self::assertSame(['module.meta'], $result['invalid_paths']);
|
||||
self::assertStringContainsString('unbekannter Attributpfad', $result['errors']['nodes[0].attrs.module.meta']);
|
||||
}
|
||||
|
||||
/** Ruling S41: the default heading level survives attrs on the same font value. */
|
||||
public function testDefaultHeadingLevelIsMergedIntoAttrs(): void
|
||||
{
|
||||
|
||||
@@ -318,6 +318,71 @@ final class DiviWriteAbilitiesTest extends TestCase
|
||||
self::assertStringContainsString('"flexType":"12_24"}}}}},"builderVersion":"5.2.1"} --><!-- wp:divi/image', $this->saved[0]);
|
||||
}
|
||||
|
||||
/** @param array<string, mixed> $attrs */
|
||||
private function updateOn(string $content, array $changes): mixed
|
||||
{
|
||||
$this->post->post_content = $content;
|
||||
|
||||
return $this->update()->execute(['post_id' => 7, 'tree_rev' => Rev::of($content), 'changes' => $changes]);
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
private static function sizing(?string $width): array
|
||||
{
|
||||
return ['module.decoration.sizing' => $width === null ? null : ['desktop' => ['flexType' => $width]]];
|
||||
}
|
||||
|
||||
/** Ruling S43: only builder column classes (or null) are accepted as new desktop widths. */
|
||||
public function testUpdateChecksTheColumnClassFormat(): void
|
||||
{
|
||||
foreach (['4_5', '13_25', '12_24,12_24', 'auto'] as $width) {
|
||||
$result = $this->update()->execute(['post_id' => 7, 'tree_rev' => $this->treeRev(), 'changes' => [
|
||||
['id' => 's0.r0.c0', 'attrs' => self::sizing($width)],
|
||||
]]);
|
||||
self::assertInstanceOf(WP_Error::class, $result, $width);
|
||||
self::assertStringContainsString('none', self::clientError($result)['fields']['changes[0].attrs.module.decoration.sizing'], $width);
|
||||
}
|
||||
|
||||
self::assertSame([], $this->saved);
|
||||
}
|
||||
|
||||
/** Ruling S43: rows that are no plain exact row are not sum-checked (none, omitted width, wrap). */
|
||||
public function testUpdateAcceptsWidthChangesInLooseRows(): void
|
||||
{
|
||||
$noneRow = str_replace('"flexType":"8_24"', '"flexType":"none"', $this->original);
|
||||
self::assertTrue($this->updateOn($noneRow, [['id' => 's0.r0.c1', 'attrs' => self::sizing('12_24')]])['ok']);
|
||||
|
||||
$omitted = str_replace(
|
||||
'{"module":{"decoration":{"sizing":{"desktop":{"value":{"flexType":"8_24"}}}}},"builderVersion":"5.2.1"}',
|
||||
'{"builderVersion":"5.2.1"}',
|
||||
$this->original
|
||||
);
|
||||
self::assertNotSame($omitted, $this->original);
|
||||
self::assertTrue($this->updateOn($omitted, [['id' => 's0.r0.c1', 'attrs' => self::sizing('12_24')]])['ok']);
|
||||
self::assertTrue($this->updateOn($omitted, [['id' => 's0.r0.c1', 'attrs' => self::sizing(null)]])['ok'], 'removal');
|
||||
|
||||
$wrap = str_replace(
|
||||
'<!-- wp:divi/row {"module":{"meta":',
|
||||
'<!-- wp:divi/row {"module":{"decoration":{"layout":{"desktop":{"value":{"flexWrap":"wrap"}}}},"meta":',
|
||||
$this->original
|
||||
);
|
||||
self::assertNotSame($wrap, $this->original);
|
||||
self::assertTrue($this->updateOn($wrap, [['id' => 's0.r0.c0', 'attrs' => self::sizing('12_24')]])['ok']);
|
||||
|
||||
self::assertTrue($this->updateOn($this->original, [['id' => 's0.r0.c0', 'attrs' => self::sizing('none')]])['ok'], 'none itself');
|
||||
self::assertCount(5, $this->saved);
|
||||
}
|
||||
|
||||
/** Ruling S43: a plain exact row stays strict; removal counts as Divi's default 24_24. */
|
||||
public function testUpdateKeepsExactRowsStrict(): void
|
||||
{
|
||||
$broken = $this->updateOn($this->original, [['id' => 's0.r0.c0', 'attrs' => self::sizing(null)]]);
|
||||
self::assertSame('lit_validation_failed', $broken->get_error_code());
|
||||
$broken = $this->updateOn($this->original, [['id' => 's0.r0.c0', 'attrs' => self::sizing('10_24')]]);
|
||||
self::assertSame('lit_validation_failed', $broken->get_error_code());
|
||||
self::assertSame([], $this->saved);
|
||||
}
|
||||
|
||||
/** Ruling S7: builder-only paths are refused for users without unfiltered_html – visible to the client. */
|
||||
public function testBuilderOnlyPathsAreRefusedForEditors(): void
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user