1010 * @group blocks
1111 */
1212class Tests_Blocks_Serialize extends WP_UnitTestCase {
13+ /**
14+ * Ensure there are no issues with special character encoding.
15+ *
16+ * @ticket 63917
17+ */
18+ public function test_attribute_encoding () {
19+ $ block = array (
20+ 'blockName ' => 'test ' ,
21+ 'attrs ' => array (
22+ 'lt ' => '< ' ,
23+ 'gt ' => '> ' ,
24+ 'amp ' => '& ' ,
25+ 'bs ' => '\\' ,
26+ 'quot ' => '" ' ,
27+ 'bs-bs-quot ' => '\\\\" ' ,
28+ ),
29+ 'innerBlocks ' => array (),
30+ 'innerHTML ' => '' ,
31+ 'innerContent ' => array (),
32+ );
33+
34+ $ expected = '<!-- wp:test {"lt":" \\u003c","gt":" \\u003e","amp":" \\u0026","bs":" \\u005c","quot":" \\u0022","bs-bs-quot":" \\u005c \\u005c \\u0022"} /--> ' ;
35+ $ this ->assertSame ( $ expected , serialize_block ( $ block ) );
36+ }
1337
1438 /**
1539 * @dataProvider data_serialize_identity_from_parsed
1640 *
1741 * @param string $original Original block markup.
42+ *
43+ * @ticket 63917
1844 */
1945 public function test_serialize_identity_from_parsed ( $ original ) {
2046 $ blocks = parse_blocks ( $ original );
@@ -24,28 +50,72 @@ public function test_serialize_identity_from_parsed( $original ) {
2450 $ this ->assertSame ( $ original , $ actual );
2551 }
2652
27- public function data_serialize_identity_from_parsed () {
53+ public static function data_serialize_identity_from_parsed (): array {
2854 return array (
29- // Void block.
30- array ( '<!-- wp:void /--> ' ),
55+ 'Void block ' =>
56+ array ( '<!-- wp:void /--> ' ),
57+
58+ 'Freeform content ($block_name = null) ' =>
59+ array ( 'Example. ' ),
3160
32- // Freeform content ($block_name = null).
33- array ( 'Example. ' ),
61+ ' Block with content' =>
62+ array ( '<!-- wp:content --> Example.<!-- /wp:content --> ' ),
3463
35- // Block with content.
36- array ( '<!-- wp:content -->Example.<!-- /wp:content --> ' ),
64+ ' Block with attributes ' =>
65+ array ( '<!-- wp:attributes {"key":"value"} / --> ' ),
3766
38- // Block with attributes.
39- array ( ' <!-- wp:attributes { "key": "value"} / --> ' ),
67+ ' Block with inner blocks ' =>
68+ array ( " <!-- wp:outer --><!-- wp:inner { \ "key \" : \ "value \ "} -->Example.<!-- /wp:inner --> \n\n Example. \n\n <!-- wp:void /--><!-- /wp:outer --> " ),
4069
41- // Block with inner blocks.
42- array ( " <!-- wp:outer --><!-- wp:inner { \ "key \" : \" value \" } -->Example.<!-- /wp:inner --> \n\n Example. \n\n <!-- wp:void /--><!-- /wp:outer --> " ),
70+ ' Block with attribute values that may conflict with HTML comment ' =>
71+ array ( ' <!-- wp:attributes { "key":" \\ u002d \\ u002d \\ u003c \\ u003e \\ u0026 \\ u0022"} /-->' ),
4372
44- // Block with attribute values that may conflict with HTML comment.
45- array ( '<!-- wp:attributes {"key":" \\ u002d \\ u002d \\ u003c \\ u003e \\ u0026 \\ u0022 "} /--> ' ),
73+ ' Block with attribute values that should not be escaped ' =>
74+ array ( '<!-- wp:attributes {"key":"€1.00 / 3 for €2.00 "} /--> ' ),
4675
47- // Block with attribute values that should not be escaped.
48- array ( '<!-- wp:attributes {"key":"€1.00 / 3 for €2.00"} /--> ' ),
76+ 'Backslashes in attributes, Gutenberg #16508 ' =>
77+ array ( '<!-- wp:attributes {"bs":" \\u005c","bsQuote":" \\u005c \\u0022","bsQuoteBs":" \\u005c \\u0022 \\u005c"} /--> ' ),
78+
79+ 'Tricky backslashes ' =>
80+ array ( '<!-- wp:attributes {"bsbsQbsbsbsQ":" \\u005c \\u005c \\u0022 \\u005c \\u005c \\u005c \\u005c \\u0022"} /--> ' ),
81+ );
82+ }
83+
84+ /**
85+ * The serialization was adjusted to use unicode escapes sequences for escaped `\` and `"`
86+ * characters inside JSON strings.
87+ *
88+ * Ensure that the previous escape form can be parsed compatibly and serialized back to
89+ * the new form.
90+ *
91+ * @see https://github.com/WordPress/wordpress-develop/pull/9558
92+ * @see https://github.com/WordPress/gutenberg/pull/71291
93+ *
94+ * @ticket 63917
95+ *
96+ * @dataProvider data_serialize_compatible_forms
97+ *
98+ * @param string $before Previous serialization form.
99+ * @param string $after New serialization form.
100+ */
101+ public function test_older_serialization_is_compatible ( string $ before , string $ after ) {
102+ $ this ->assertNotSame ( $ before , $ after , 'The same serialization should not be provided for before and after. ' );
103+ $ blocks = parse_blocks ( $ before );
104+ $ actual = serialize_blocks ( $ blocks );
105+ $ this ->assertSame ( $ after , $ actual );
106+ }
107+
108+ public static function data_serialize_compatible_forms (): array {
109+ return array (
110+ 'Special characters ' => array (
111+ '<!-- wp:attributes {"lt":" \\u003c","gt":" \\u003e","amp":" \\u0026","bs":" \\\\","quot":" \\u0022"} /--> ' ,
112+ '<!-- wp:attributes {"lt":" \\u003c","gt":" \\u003e","amp":" \\u0026","bs":" \\u005c","quot":" \\u0022"} /--> ' ,
113+ ),
114+
115+ 'Backslashes ' => array (
116+ '<!-- wp:attributes {"bs":" \\\\","bsQuote":" \\\\\\u0022","bsQuoteBs":" \\\\\\u0022 \\\\"} /--> ' ,
117+ '<!-- wp:attributes {"bs":" \\u005c","bsQuote":" \\u005c \\u0022","bsQuoteBs":" \\u005c \\u0022 \\u005c"} /--> ' ,
118+ ),
49119 );
50120 }
51121
0 commit comments