Every fixture page, also with Windows line endings. */ public static function fixtures(): array { $cases = []; foreach (glob(dirname(__DIR__, 4) . '/Fixtures/divi/*.html') ?: [] as $file) { $content = (string) file_get_contents($file); $cases[basename($file)] = [$content]; $cases[basename($file) . ' (CRLF)'] = [str_replace("\n", "\r\n", $content)]; } return $cases; } /** @dataProvider fixtures */ public function testParseThenSerializeIsByteIdentical(string $content): void { self::assertSame($content, Serializer::document((new Parser())->parse($content))); } public function testFixturesArePresent(): void { $names = array_map('basename', glob(dirname(__DIR__, 4) . '/Fixtures/divi/*.html') ?: []); self::assertContains('synthetic-basic.html', $names); self::assertContains('synthetic-mixed.html', $names); self::assertContains('converted-landing.html', $names); self::assertContains('converted-features.html', $names); } public function testBuildsTheTree(): void { $document = (new Parser())->parse($this->fixture('synthetic-basic.html')); $placeholder = $document->children()[0]; self::assertSame('divi/placeholder', $placeholder->name()); $sections = $placeholder->children(); self::assertCount(2, $sections); self::assertSame('divi/section', $sections[0]->name()); self::assertFalse($sections[0]->isOpaque()); self::assertSame( '$variable({"type":"color","value":{"name":"gcid-primary-color","settings":{}}})$', $sections[0]->attrs()['module']['decoration']['background']['desktop']['value']['color'] ); $columns = $sections[0]->children()[0]->children(); self::assertSame(['divi/column', 'divi/column'], array_map(static fn (Block $b): string => $b->name(), $columns)); self::assertTrue($columns[0]->children()[0]->isVoid()); self::assertSame('image', $columns[0]->children()[0]->shortName()); self::assertSame( 'Willkommen bei Müller & Söhne', $columns[1]->children()[0]->attrs()['title']['innerContent']['desktop']['value'] ); } public function testKeepsTextBetweenBlocksAndNamesCoreBlocks(): void { $document = (new Parser())->parse("\n

x

\n\n\ntext"); self::assertSame('core/paragraph', $document->children()[0]->name()); self::assertSame(["\n

x

\n"], $document->children()[0]->parts()); self::assertSame("\n\ntext", $document->parts()[1]); } public function testMarksGlobalAndUndecodableBlocksOpaque(): void { $document = (new Parser())->parse($this->fixture('synthetic-mixed.html')); $placeholder = $document->children()[1]; $second = $placeholder->children()[1]; [$globalLayout, $globalRow, $globalWithChild] = $second->children(); self::assertTrue($globalLayout->isOpaque()); self::assertTrue($globalLayout->isGlobal()); self::assertTrue($globalRow->isOpaque()); self::assertTrue($globalRow->isGlobal()); self::assertTrue($globalWithChild->isOpaque()); self::assertFalse($second->isOpaque()); $broken = (new Parser())->parse(''); self::assertTrue($broken->children()[0]->isOpaque()); self::assertSame([], $broken->children()[0]->attrs()); } public function testKeepsEmptyAndListLikeObjectsAsObjects(): void { $document = (new Parser())->parse($this->fixture('synthetic-mixed.html')); $attrs = $document->children()[1]->children()[1]->attrs(); self::assertInstanceOf(stdClass::class, $attrs['module']['decoration']['spacing']['desktop']['value']); self::assertSame([], $attrs['module']['decoration']['background']['desktop']['value']); self::assertInstanceOf(stdClass::class, $attrs['localAttrs']); } public function testDivi4ShortcodesAreOneTextPart(): void { $content = $this->fixture('divi4-shortcodes.html'); $document = (new Parser())->parse($content); self::assertSame([], $document->children()); self::assertSame([$content], $document->parts()); } /** @return array */ public static function malformed(): array { return [ 'closer without opener' => [''], 'unclosed block' => [''], 'crossed blocks' => [''], ]; } /** @dataProvider malformed */ public function testRefusesUnbalancedMarkup(string $content): void { $this->expectException(MalformedMarkup::class); (new Parser())->parse($content); } private function fixture(string $name): string { return (string) file_get_contents(dirname(__DIR__, 4) . '/Fixtures/divi/' . $name); } }