Changeset 62478 for trunk/tests/phpunit/tests/block-supports/states.php
- Timestamp:
- 06/09/2026 04:25:45 AM (3 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/tests/phpunit/tests/block-supports/states.php
r62453 r62478 38 38 * @param string $block_name Block name. 39 39 * @param array $selectors Optional block selectors, e.g. array( 'root' => '.foo .bar' ). 40 * @param array $supports Optional block supports. 40 41 * @return WP_Block_Type 41 42 */ 42 private function ensure_block_registered( $block_name, $selectors = array() ) {43 private function ensure_block_registered( $block_name, $selectors = array(), $supports = array() ) { 43 44 $registered_block = WP_Block_Type_Registry::get_instance()->get_registered( $block_name ); 44 45 if ( $registered_block ) { … … 57 58 if ( ! empty( $selectors ) ) { 58 59 $args['selectors'] = $selectors; 60 } 61 if ( ! empty( $supports ) ) { 62 $args['supports'] = $supports; 59 63 } 60 64 register_block_type( $block_name, $args ); … … 838 842 839 843 /** 844 * Tests that a responsive block gap state generates layout spacing CSS. 845 * 846 * Responsive layout CSS is owned by wp_render_layout_support_flag() 847 * so it shares a selector with the base layout (the inner block wrapper for 848 * wrapper blocks) instead of being scoped to a separate `wp-states-...` class. 849 * 850 * @covers ::wp_render_layout_support_flag 851 * 852 * @ticket 65164 853 */ 854 public function test_responsive_block_gap_state_generates_layout_spacing_css() { 855 $this->ensure_block_registered( 856 'test/responsive-flow-layout-state', 857 array(), 858 array( 859 'layout' => array( 860 'default' => array( 861 'type' => 'default', 862 ), 863 ), 864 'spacing' => array( 865 'blockGap' => true, 866 ), 867 ) 868 ); 869 870 add_theme_support( 'appearance-tools' ); 871 WP_Theme_JSON_Resolver::clean_cached_data(); 872 873 try { 874 $block_content = '<div class="wp-block-test"><p>One</p><p>Two</p></div>'; 875 $block = array( 876 'blockName' => 'test/responsive-flow-layout-state', 877 'innerContent' => array( '<div class="wp-block-test">', null, '</div>' ), 878 'attrs' => array( 879 'layout' => array( 880 'type' => 'default', 881 ), 882 'style' => array( 883 'mobile' => array( 884 'spacing' => array( 885 'blockGap' => '12px', 886 ), 887 ), 888 ), 889 ), 890 ); 891 892 $actual = wp_render_layout_support_flag( $block_content, $block ); 893 preg_match( '/wp-container-test-responsive-flow-layout-state-is-layout-[a-f0-9]{8}/', $actual, $matches ); 894 $this->assertNotEmpty( $matches, "wp-container class missing in: $actual" ); 895 $container_class = $matches[0]; 896 $actual_stylesheet = wp_style_engine_get_stylesheet_from_context( 'block-supports', array( 'prettify' => false ) ); 897 898 $this->assertStringContainsString( 899 '@media (width <= 480px){.' . $container_class . ' > *{margin-block-start:0;margin-block-end:0;}}', 900 $actual_stylesheet 901 ); 902 $this->assertStringContainsString( 903 '@media (width <= 480px){.' . $container_class . ' > * + *{margin-block-start:12px;margin-block-end:0;}}', 904 $actual_stylesheet 905 ); 906 } finally { 907 remove_theme_support( 'appearance-tools' ); 908 WP_Theme_JSON_Resolver::clean_cached_data(); 909 } 910 } 911 912 /** 913 * Tests that responsive block gap state CSS uses the block's active layout type. 914 * 915 * @covers ::wp_render_layout_support_flag 916 * 917 * @ticket 65164 918 */ 919 public function test_responsive_block_gap_state_uses_active_layout_type() { 920 $this->ensure_block_registered( 921 'test/responsive-flex-layout-state', 922 array(), 923 array( 924 'layout' => array( 925 'default' => array( 926 'type' => 'flex', 927 ), 928 ), 929 'spacing' => array( 930 'blockGap' => true, 931 ), 932 ) 933 ); 934 935 add_theme_support( 'appearance-tools' ); 936 WP_Theme_JSON_Resolver::clean_cached_data(); 937 938 try { 939 $block_content = '<div class="wp-block-test"><p>One</p><p>Two</p></div>'; 940 $block = array( 941 'blockName' => 'test/responsive-flex-layout-state', 942 'innerContent' => array( '<div class="wp-block-test">', null, '</div>' ), 943 'attrs' => array( 944 'layout' => array( 945 'type' => 'flex', 946 ), 947 'style' => array( 948 'mobile' => array( 949 'spacing' => array( 950 'blockGap' => '12px', 951 ), 952 ), 953 ), 954 ), 955 ); 956 957 $actual = wp_render_layout_support_flag( $block_content, $block ); 958 preg_match( '/wp-container-test-responsive-flex-layout-state-is-layout-[a-f0-9]{8}/', $actual, $matches ); 959 $this->assertNotEmpty( $matches, "wp-container class missing in: $actual" ); 960 $container_class = $matches[0]; 961 $actual_stylesheet = wp_style_engine_get_stylesheet_from_context( 'block-supports', array( 'prettify' => false ) ); 962 963 $this->assertStringContainsString( 964 '@media (width <= 480px){.' . $container_class . '{gap:12px;}}', 965 $actual_stylesheet 966 ); 967 } finally { 968 remove_theme_support( 'appearance-tools' ); 969 WP_Theme_JSON_Resolver::clean_cached_data(); 970 } 971 } 972 973 /** 974 * Tests that responsive layout state CSS can override grid layout values. 975 * 976 * @covers ::wp_render_layout_support_flag 977 * 978 * @ticket 65164 979 */ 980 public function test_responsive_layout_state_generates_grid_layout_css() { 981 $this->ensure_block_registered( 982 'test/responsive-grid-layout-state', 983 array(), 984 array( 985 'layout' => array( 986 'default' => array( 987 'type' => 'grid', 988 ), 989 ), 990 ) 991 ); 992 993 $block_content = '<div class="wp-block-test"><p>One</p><p>Two</p></div>'; 994 $block = array( 995 'blockName' => 'test/responsive-grid-layout-state', 996 'innerContent' => array( '<div class="wp-block-test">', null, '</div>' ), 997 'attrs' => array( 998 'layout' => array( 999 'type' => 'grid', 1000 ), 1001 'style' => array( 1002 'mobile' => array( 1003 'layout' => array( 1004 'minimumColumnWidth' => '8rem', 1005 ), 1006 ), 1007 ), 1008 ), 1009 ); 1010 1011 $actual = wp_render_layout_support_flag( $block_content, $block ); 1012 preg_match( '/wp-container-test-responsive-grid-layout-state-is-layout-[a-f0-9]{8}/', $actual, $matches ); 1013 $this->assertNotEmpty( $matches, "wp-container class missing in: $actual" ); 1014 $container_class = $matches[0]; 1015 $actual_stylesheet = wp_style_engine_get_stylesheet_from_context( 'block-supports', array( 'prettify' => false ) ); 1016 1017 $this->assertStringContainsString( 1018 '@media (width <= 480px){.' . $container_class . '{grid-template-columns:repeat(auto-fill, minmax(min(8rem, 100%), 1fr));}}', 1019 $actual_stylesheet 1020 ); 1021 } 1022 1023 /** 1024 * Tests that responsive layout state CSS can override grid columns. 1025 * 1026 * @covers ::wp_render_layout_support_flag 1027 * 1028 * @ticket 65164 1029 */ 1030 public function test_responsive_layout_state_generates_grid_column_count_css() { 1031 $this->ensure_block_registered( 1032 'test/responsive-grid-column-layout-state', 1033 array(), 1034 array( 1035 'layout' => array( 1036 'default' => array( 1037 'type' => 'grid', 1038 ), 1039 ), 1040 ) 1041 ); 1042 1043 $block_content = '<div class="wp-block-test"><p>One</p><p>Two</p></div>'; 1044 $block = array( 1045 'blockName' => 'test/responsive-grid-column-layout-state', 1046 'innerContent' => array( '<div class="wp-block-test">', null, '</div>' ), 1047 'attrs' => array( 1048 'layout' => array( 1049 'type' => 'grid', 1050 ), 1051 'style' => array( 1052 'mobile' => array( 1053 'layout' => array( 1054 'columnCount' => 3, 1055 ), 1056 ), 1057 ), 1058 ), 1059 ); 1060 1061 $actual = wp_render_layout_support_flag( $block_content, $block ); 1062 preg_match( '/wp-container-test-responsive-grid-column-layout-state-is-layout-[a-f0-9]{8}/', $actual, $matches ); 1063 $this->assertNotEmpty( $matches, "wp-container class missing in: $actual" ); 1064 $container_class = $matches[0]; 1065 $actual_stylesheet = wp_style_engine_get_stylesheet_from_context( 'block-supports', array( 'prettify' => false ) ); 1066 1067 $this->assertStringContainsString( 1068 '@media (width <= 480px){.' . $container_class . '{grid-template-columns:repeat(3, minmax(0, 1fr));}}', 1069 $actual_stylesheet 1070 ); 1071 } 1072 1073 /** 1074 * Tests that different responsive layout states generate different container 1075 * classes, even when the base layout configuration is identical. 1076 * 1077 * @covers ::wp_render_layout_support_flag 1078 * 1079 * @ticket 65164 1080 */ 1081 public function test_responsive_layout_state_generates_distinct_container_classes_for_distinct_viewport_styles() { 1082 $this->ensure_block_registered( 1083 'test/responsive-grid-distinct-layout-state', 1084 array(), 1085 array( 1086 'layout' => array( 1087 'default' => array( 1088 'type' => 'grid', 1089 ), 1090 ), 1091 ) 1092 ); 1093 1094 $block_content = '<div class="wp-block-test"><p>One</p><p>Two</p></div>'; 1095 $base_block = array( 1096 'blockName' => 'test/responsive-grid-distinct-layout-state', 1097 'innerContent' => array( '<div class="wp-block-test">', null, '</div>' ), 1098 'attrs' => array( 1099 'layout' => array( 1100 'type' => 'grid', 1101 ), 1102 ), 1103 ); 1104 $first_block = array_replace_recursive( 1105 $base_block, 1106 array( 1107 'attrs' => array( 1108 'style' => array( 1109 'mobile' => array( 1110 'layout' => array( 1111 'columnCount' => 3, 1112 ), 1113 ), 1114 ), 1115 ), 1116 ) 1117 ); 1118 $second_block = array_replace_recursive( 1119 $base_block, 1120 array( 1121 'attrs' => array( 1122 'style' => array( 1123 'mobile' => array( 1124 'layout' => array( 1125 'columnCount' => 4, 1126 ), 1127 ), 1128 ), 1129 ), 1130 ) 1131 ); 1132 1133 $first_actual = wp_render_layout_support_flag( $block_content, $first_block ); 1134 $second_actual = wp_render_layout_support_flag( $block_content, $second_block ); 1135 1136 preg_match( '/wp-container-test-responsive-grid-distinct-layout-state-is-layout-[a-f0-9]{8}/', $first_actual, $first_matches ); 1137 preg_match( '/wp-container-test-responsive-grid-distinct-layout-state-is-layout-[a-f0-9]{8}/', $second_actual, $second_matches ); 1138 1139 $this->assertNotEmpty( $first_matches, "wp-container class missing in: $first_actual" ); 1140 $this->assertNotEmpty( $second_matches, "wp-container class missing in: $second_actual" ); 1141 1142 $first_container_class = $first_matches[0]; 1143 $second_container_class = $second_matches[0]; 1144 1145 $this->assertNotSame( $first_container_class, $second_container_class ); 1146 1147 $actual_stylesheet = wp_style_engine_get_stylesheet_from_context( 'block-supports', array( 'prettify' => false ) ); 1148 1149 $this->assertStringContainsString( 1150 '@media (width <= 480px){.' . $first_container_class . '{grid-template-columns:repeat(3, minmax(0, 1fr));}}', 1151 $actual_stylesheet 1152 ); 1153 $this->assertStringContainsString( 1154 '@media (width <= 480px){.' . $second_container_class . '{grid-template-columns:repeat(4, minmax(0, 1fr));}}', 1155 $actual_stylesheet 1156 ); 1157 } 1158 1159 /** 1160 * Tests that responsive grid layout and block gap state CSS are both generated. 1161 * 1162 * @covers ::wp_render_layout_support_flag 1163 * 1164 * @ticket 65164 1165 */ 1166 public function test_responsive_layout_state_generates_grid_columns_and_gap_css() { 1167 $this->ensure_block_registered( 1168 'test/responsive-grid-columns-gap-layout-state', 1169 array(), 1170 array( 1171 'layout' => array( 1172 'default' => array( 1173 'type' => 'grid', 1174 ), 1175 ), 1176 'spacing' => array( 1177 'blockGap' => true, 1178 ), 1179 ) 1180 ); 1181 1182 add_theme_support( 'appearance-tools' ); 1183 WP_Theme_JSON_Resolver::clean_cached_data(); 1184 1185 try { 1186 $block_content = '<div class="wp-block-test"><p>One</p><p>Two</p></div>'; 1187 $block = array( 1188 'blockName' => 'test/responsive-grid-columns-gap-layout-state', 1189 'innerContent' => array( '<div class="wp-block-test">', null, '</div>' ), 1190 'attrs' => array( 1191 'layout' => array( 1192 'type' => 'grid', 1193 ), 1194 'style' => array( 1195 'mobile' => array( 1196 'layout' => array( 1197 'columnCount' => 3, 1198 ), 1199 'spacing' => array( 1200 'blockGap' => '12px', 1201 ), 1202 ), 1203 ), 1204 ), 1205 ); 1206 1207 $actual = wp_render_layout_support_flag( $block_content, $block ); 1208 preg_match( '/wp-container-test-responsive-grid-columns-gap-layout-state-is-layout-[a-f0-9]{8}/', $actual, $matches ); 1209 $this->assertNotEmpty( $matches, "wp-container class missing in: $actual" ); 1210 $container_class = $matches[0]; 1211 $actual_stylesheet = wp_style_engine_get_stylesheet_from_context( 'block-supports', array( 'prettify' => false ) ); 1212 1213 $this->assertStringContainsString( 1214 '@media (width <= 480px){.' . $container_class . '{grid-template-columns:repeat(3, minmax(0, 1fr));gap:12px;}}', 1215 $actual_stylesheet 1216 ); 1217 } finally { 1218 remove_theme_support( 'appearance-tools' ); 1219 WP_Theme_JSON_Resolver::clean_cached_data(); 1220 } 1221 } 1222 1223 /** 1224 * Tests that responsive grid block gap CSS does not repeat unchanged layout declarations. 1225 * 1226 * @covers ::wp_render_layout_support_flag 1227 * 1228 * @ticket 65164 1229 */ 1230 public function test_responsive_grid_block_gap_state_only_outputs_changed_layout_css() { 1231 $this->ensure_block_registered( 1232 'test/responsive-grid-gap-state', 1233 array(), 1234 array( 1235 'layout' => array( 1236 'default' => array( 1237 'type' => 'grid', 1238 'minimumColumnWidth' => '12rem', 1239 ), 1240 ), 1241 'spacing' => array( 1242 'blockGap' => true, 1243 ), 1244 ) 1245 ); 1246 1247 add_theme_support( 'appearance-tools' ); 1248 WP_Theme_JSON_Resolver::clean_cached_data(); 1249 1250 try { 1251 $block_content = '<div class="wp-block-test"><p>One</p><p>Two</p></div>'; 1252 $block = array( 1253 'blockName' => 'test/responsive-grid-gap-state', 1254 'innerContent' => array( '<div class="wp-block-test">', null, '</div>' ), 1255 'attrs' => array( 1256 'layout' => array( 1257 'type' => 'grid', 1258 'minimumColumnWidth' => '12rem', 1259 ), 1260 'style' => array( 1261 'tablet' => array( 1262 'spacing' => array( 1263 'blockGap' => '12px', 1264 ), 1265 ), 1266 ), 1267 ), 1268 ); 1269 1270 $actual = wp_render_layout_support_flag( $block_content, $block ); 1271 preg_match( '/wp-container-test-responsive-grid-gap-state-is-layout-[a-f0-9]{8}/', $actual, $matches ); 1272 $this->assertNotEmpty( $matches, "wp-container class missing in: $actual" ); 1273 $container_class = $matches[0]; 1274 $actual_stylesheet = wp_style_engine_get_stylesheet_from_context( 'block-supports', array( 'prettify' => false ) ); 1275 1276 $this->assertStringContainsString( 1277 '@media (480px < width <= 782px){.' . $container_class . '{gap:12px;}}', 1278 $actual_stylesheet 1279 ); 1280 $this->assertStringNotContainsString( 1281 '@media (480px < width <= 782px){.' . $container_class . '{grid-template-columns:', 1282 $actual_stylesheet 1283 ); 1284 $this->assertStringNotContainsString( 1285 '@media (480px < width <= 782px){.' . $container_class . '{container-type:', 1286 $actual_stylesheet 1287 ); 1288 } finally { 1289 remove_theme_support( 'appearance-tools' ); 1290 WP_Theme_JSON_Resolver::clean_cached_data(); 1291 } 1292 } 1293 1294 /** 1295 * Tests that responsive child layout state CSS is generated. 1296 * 1297 * @covers ::wp_render_layout_support_flag 1298 * 1299 * @ticket 65164 1300 */ 1301 public function test_responsive_child_layout_state_generates_grid_span_css() { 1302 $this->ensure_block_registered( 'test/responsive-child-layout-state' ); 1303 1304 $block_content = '<p>Some text.</p>'; 1305 $block = array( 1306 'blockName' => 'test/responsive-child-layout-state', 1307 'innerContent' => array( '<p>Some text.</p>' ), 1308 'attrs' => array( 1309 'style' => array( 1310 'mobile' => array( 1311 'layout' => array( 1312 'columnSpan' => '2', 1313 ), 1314 ), 1315 ), 1316 ), 1317 'parentLayout' => array( 1318 'type' => 'grid', 1319 'columnCount' => 3, 1320 ), 1321 ); 1322 1323 $actual = wp_render_layout_support_flag( $block_content, $block ); 1324 preg_match( '/wp-container-content-[a-f0-9]{8}/', $actual, $matches ); 1325 $this->assertNotEmpty( $matches, "wp-container-content class missing in: $actual" ); 1326 $container_content_class = $matches[0]; 1327 $actual_stylesheet = wp_style_engine_get_stylesheet_from_context( 'block-supports', array( 'prettify' => false ) ); 1328 1329 $this->assertStringContainsString( 1330 '@media (width <= 480px){.' . $container_content_class . '{grid-column:span 2;}}', 1331 $actual_stylesheet 1332 ); 1333 } 1334 1335 /** 1336 * Tests that a wrapper block (markup with an inner content wrapper) receives 1337 * responsive grid layout CSS scoped to the inner wrapper, not the outermost tag. 1338 * 1339 * Regression test for the bug where wp-states-... was added to the outer tag 1340 * while the wp-container-... layout class lives on the inner wrapper, causing 1341 * the responsive @media rule to apply to the wrong element. 1342 * 1343 * @covers ::wp_render_layout_support_flag 1344 * 1345 * @ticket 65164 1346 */ 1347 public function test_responsive_layout_state_targets_inner_wrapper_for_wrapper_blocks() { 1348 $this->ensure_block_registered( 1349 'test/responsive-wrapper-grid-state', 1350 array(), 1351 array( 1352 'layout' => array( 1353 'default' => array( 1354 'type' => 'grid', 1355 ), 1356 ), 1357 ) 1358 ); 1359 1360 $block_content = '<div class="wp-block-wrapper"><div class="wp-block-wrapper__inner-container"><p>One</p></div></div>'; 1361 $block = array( 1362 'blockName' => 'test/responsive-wrapper-grid-state', 1363 'innerContent' => array( 1364 '<div class="wp-block-wrapper"><div class="wp-block-wrapper__inner-container">', 1365 null, 1366 '</div></div>', 1367 ), 1368 'attrs' => array( 1369 'layout' => array( 1370 'type' => 'grid', 1371 ), 1372 'style' => array( 1373 'mobile' => array( 1374 'layout' => array( 1375 'columnCount' => 3, 1376 ), 1377 ), 1378 ), 1379 ), 1380 ); 1381 1382 $actual = wp_render_layout_support_flag( $block_content, $block ); 1383 1384 // The wp-container-...-is-layout-... class should land on the inner wrapper. 1385 $this->assertMatchesRegularExpression( 1386 '/<div class="wp-block-wrapper__inner-container [^"]*wp-container-test-responsive-wrapper-grid-state-is-layout-[a-f0-9]{8}/', 1387 $actual 1388 ); 1389 1390 preg_match( '/wp-container-test-responsive-wrapper-grid-state-is-layout-[a-f0-9]{8}/', $actual, $matches ); 1391 $container_class = $matches[0]; 1392 $actual_stylesheet = wp_style_engine_get_stylesheet_from_context( 'block-supports', array( 'prettify' => false ) ); 1393 1394 // The responsive @media rule must target the same selector that lives on 1395 // the inner wrapper element. 1396 $this->assertStringContainsString( 1397 '@media (width <= 480px){.' . $container_class . '{grid-template-columns:repeat(3, minmax(0, 1fr));}}', 1398 $actual_stylesheet 1399 ); 1400 } 1401 1402 /** 840 1403 * Tests that state declarations are marked important. 841 1404 *
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)