row > column (24_24) > blurb. */ private static function section(): Block { $content = DiviFixtures::markup('stage3/library--library-abschnitt.html'); return LibraryContent::roots(LibraryContent::load(new Parser(), $content))[0]; } private static function blurbOf(Block $section): Block { return $section->children()[0]->children()[0]->children()[0]; } public function testAdminLabelsAndBuilderVersionDoNotCount(): void { $a = self::section(); $b = $a->copy(); $attrs = $b->attrs(); $attrs['module']['meta']['adminLabel']['desktop']['value'] = 'Anderes Label'; $attrs['builderVersion'] = '5.3.0'; $b->setAttrs($attrs); self::assertSame(16, strlen(Fingerprint::content($a))); self::assertSame(Fingerprint::content($a), Fingerprint::content($b)); self::assertSame(Fingerprint::structure($a), Fingerprint::structure($b)); } public function testOtherTextsKeepTheStructureButNotTheContent(): void { $a = self::section(); $b = $a->copy(); $blurb = self::blurbOf($b); $attrs = $blurb->attrs(); $attrs['title']['innerContent']['desktop']['value'] = 'Anderer Titel'; $blurb->setAttrs($attrs); self::assertSame(Fingerprint::structure($a), Fingerprint::structure($b)); self::assertNotSame(Fingerprint::content($a), Fingerprint::content($b)); } public function testColumnLayoutAndModuleTypesChangeTheStructure(): void { $a = self::section(); $b = $a->copy(); $column = $b->children()[0]->children()[0]; $attrs = $column->attrs(); $attrs['module']['decoration']['sizing']['desktop']['value']['flexType'] = '12_24'; $column->setAttrs($attrs); $c = Block::create('divi/section', [], [Block::create('divi/row', [], [Block::create('divi/column', [], [ Block::create('divi/text'), ])])]); self::assertNotSame(Fingerprint::structure($a), Fingerprint::structure($b)); self::assertNotSame(Fingerprint::structure($a), Fingerprint::structure($c)); } /** The section of 1055 with $extra inserted at the end of its column (review of Task 15, ruling Q25). */ private static function sectionWith(string $extra): Block { $markup = DiviFixtures::markup('stage3/library--library-abschnitt.html'); $at = strrpos($markup, ''); $markup = substr($markup, 0, (int) $at) . $extra . substr($markup, (int) $at); return LibraryContent::roots(LibraryContent::load(new Parser(), $markup))[0]; } /** @return array */ public static function visibleExtras(): array { return [ 'raw html between blocks' => ['

ONLY ON B

', '

ONLY ON C

'], 'core paragraph' => [ '

ONLY ON B

', '

ONLY ON C

', ], 'divi 4 shortcode text' => ['[et_pb_text]ONLY ON B[/et_pb_text]', '[et_pb_text]ONLY ON C[/et_pb_text]'], ]; } /** * Ruling Q25: text parts are visible – raw HTML between blocks and the inner HTML of core blocks count * for the content, like attributes. * * @dataProvider visibleExtras */ public function testVisibleTextPartsCountForTheContent(string $extra, string $other): void { $plain = self::section(); self::assertNotSame(Fingerprint::content($plain), Fingerprint::content(self::sectionWith($extra))); self::assertNotSame( Fingerprint::content(self::sectionWith($extra)), Fingerprint::content(self::sectionWith($other)) ); self::assertNotSame(Fingerprint::canonical($plain), Fingerprint::canonical(self::sectionWith($extra))); } public function testRawTextKeepsTheStructureAndWhitespaceNeverCounts(): void { $plain = self::section(); self::assertSame(Fingerprint::structure($plain), Fingerprint::structure(self::sectionWith('

x

'))); self::assertSame(Fingerprint::content($plain), Fingerprint::content(self::sectionWith("\n \n"))); self::assertSame(Fingerprint::canonical($plain), Fingerprint::canonical(self::sectionWith("\n\t"))); } /** Opaque blocks count with all their bytes (a global instance's snapshot included). */ public function testOpaqueBlocksCountWithAllTheirBytes(): void { $instance = static fn (string $text): Block => LibraryContent::roots(LibraryContent::load( new Parser(), '' . '

' . $text . '

' . '' ))[0]; self::assertNotSame(Fingerprint::content($instance('a')), Fingerprint::content($instance('b'))); } }