Changeset 61174 for trunk/tests/phpunit/tests/template.php
- Timestamp:
- 11/07/2025 04:27:45 AM (3 months ago)
- File:
-
- 1 edited
-
trunk/tests/phpunit/tests/template.php (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/tests/phpunit/tests/template.php
r61140 r61174 128 128 $wp_scripts = null; 129 129 $wp_styles = null; 130 wp_scripts(); 131 wp_styles(); 132 133 $this->original_theme_features = $GLOBALS['_wp_theme_features']; 130 134 131 foreach ( self::RESTORED_CONFIG_OPTIONS as $option ) { 135 132 $this->original_ini_config[ $option ] = ini_get( $option ); … … 142 139 $wp_styles = $this->original_wp_styles; 143 140 144 $GLOBALS['_wp_theme_features'] = $this->original_theme_features;145 141 foreach ( $this->original_ini_config as $option => $value ) { 146 142 ini_set( $option, $value ); … … 150 146 unregister_taxonomy( 'taxo' ); 151 147 $this->set_permalink_structure( '' ); 148 152 149 parent::tear_down(); 153 150 } … … 631 628 'wp_template_enhancement_output_buffer', 632 629 static function () { 633 return '<html >Hey!</html>';630 return '<html lang="en"><head><meta charset="utf-8"></head><body>Hey!</body></html>'; 634 631 } 635 632 ); … … 1423 1420 }, 1424 1421 'expected_load_separate' => false, 1425 'expected_on_demand' => true,1422 'expected_on_demand' => false, 1426 1423 'expected_buffer_started' => false, 1427 1424 ), … … 1476 1473 * Data provider. 1477 1474 * 1478 * @return array<string, array{set_up: Closure|null }>1475 * @return array<string, array{set_up: Closure|null, inline_size_limit: int, expected_styles: array{ HEAD: string[], BODY: string[] }}> 1479 1476 */ 1480 1477 public function data_wp_hoist_late_printed_styles(): array { 1478 $common_expected_head_styles = array( 1479 'wp-img-auto-sizes-contain-inline-css', 1480 'early-css', 1481 'early-inline-css', 1482 'wp-emoji-styles-inline-css', 1483 'wp-block-library-css', 1484 'wp-block-separator-css', 1485 'global-styles-inline-css', 1486 'core-block-supports-inline-css', 1487 'classic-theme-styles-css', 1488 'normal-css', 1489 'normal-inline-css', 1490 'wp-custom-css', 1491 'late-css', 1492 'late-inline-css', 1493 ); 1494 1481 1495 return array( 1482 'no_actions_removed' => array( 1483 'set_up' => null, 1484 ), 1485 '_wp_footer_scripts_removed' => array( 1486 'set_up' => static function () { 1496 'standard_classic_theme_config_with_min_styles_inlined' => array( 1497 'set_up' => null, 1498 'inline_size_limit' => 0, 1499 'expected_styles' => array( 1500 'HEAD' => $common_expected_head_styles, 1501 'BODY' => array(), 1502 ), 1503 ), 1504 'standard_classic_theme_config_with_max_styles_inlined' => array( 1505 'set_up' => null, 1506 'inline_size_limit' => PHP_INT_MAX, 1507 'expected_styles' => array( 1508 'HEAD' => array( 1509 'wp-img-auto-sizes-contain-inline-css', 1510 'early-css', 1511 'early-inline-css', 1512 'wp-emoji-styles-inline-css', 1513 'wp-block-library-inline-css', 1514 'wp-block-separator-inline-css', 1515 'global-styles-inline-css', 1516 'core-block-supports-inline-css', 1517 'classic-theme-styles-inline-css', 1518 'normal-css', 1519 'normal-inline-css', 1520 'wp-custom-css', 1521 'late-css', 1522 'late-inline-css', 1523 ), 1524 'BODY' => array(), 1525 ), 1526 ), 1527 'standard_classic_theme_config_extra_block_library_inline_style' => array( 1528 'set_up' => static function () { 1529 add_action( 1530 'enqueue_block_assets', 1531 static function () { 1532 wp_add_inline_style( 'wp-block-library', '/* Extra CSS which prevents empty inline style containing placeholder from being removed. */' ); 1533 } 1534 ); 1535 }, 1536 'inline_size_limit' => 0, 1537 'expected_styles' => array( 1538 'HEAD' => ( function ( $expected_styles ) { 1539 // Insert 'wp-block-library-inline-css' right after 'wp-block-library-css'. 1540 $i = array_search( 'wp-block-library-css', $expected_styles, true ); 1541 $this->assertIsInt( $i, 'Expected wp-block-library-css to be among the styles.' ); 1542 array_splice( $expected_styles, $i + 1, 0, 'wp-block-library-inline-css' ); 1543 return $expected_styles; 1544 } )( $common_expected_head_styles ), 1545 'BODY' => array(), 1546 ), 1547 ), 1548 'classic_theme_opt_out_separate_block_styles' => array( 1549 'set_up' => static function () { 1550 add_filter( 'should_load_separate_core_block_assets', '__return_false' ); 1551 }, 1552 'inline_size_limit' => 0, 1553 'expected_styles' => array( 1554 'HEAD' => array( 1555 'wp-img-auto-sizes-contain-inline-css', 1556 'early-css', 1557 'early-inline-css', 1558 'wp-emoji-styles-inline-css', 1559 'wp-block-library-css', 1560 'classic-theme-styles-css', 1561 'global-styles-inline-css', 1562 'normal-css', 1563 'normal-inline-css', 1564 'wp-custom-css', 1565 ), 1566 'BODY' => array( 1567 'late-css', 1568 'late-inline-css', 1569 'core-block-supports-inline-css', 1570 ), 1571 ), 1572 ), 1573 '_wp_footer_scripts_removed' => array( 1574 'set_up' => static function () { 1487 1575 remove_action( 'wp_print_footer_scripts', '_wp_footer_scripts' ); 1488 1576 }, 1489 ), 1490 'wp_print_footer_scripts_removed' => array( 1491 'set_up' => static function () { 1577 'inline_size_limit' => 0, 1578 'expected_styles' => array( 1579 'HEAD' => $common_expected_head_styles, 1580 'BODY' => array(), 1581 ), 1582 ), 1583 'wp_print_footer_scripts_removed' => array( 1584 'set_up' => static function () { 1492 1585 remove_action( 'wp_footer', 'wp_print_footer_scripts', 20 ); 1493 1586 }, 1494 ), 1495 'both_actions_removed' => array( 1496 'set_up' => static function () { 1587 'inline_size_limit' => 0, 1588 'expected_styles' => array( 1589 'HEAD' => $common_expected_head_styles, 1590 'BODY' => array(), 1591 ), 1592 ), 1593 'both_actions_removed' => array( 1594 'set_up' => static function () { 1497 1595 remove_action( 'wp_print_footer_scripts', '_wp_footer_scripts' ); 1498 1596 remove_action( 'wp_footer', 'wp_print_footer_scripts' ); 1499 1597 }, 1500 ), 1501 'block_library_removed' => array( 1502 'set_up' => static function () { 1503 wp_deregister_style( 'wp-block-library' ); 1504 }, 1598 'inline_size_limit' => 0, 1599 'expected_styles' => array( 1600 'HEAD' => $common_expected_head_styles, 1601 'BODY' => array(), 1602 ), 1603 ), 1604 'disable_block_library' => array( 1605 'set_up' => static function () { 1606 add_action( 1607 'enqueue_block_assets', 1608 function (): void { 1609 wp_deregister_style( 'wp-block-library' ); 1610 wp_register_style( 'wp-block-library', '' ); 1611 } 1612 ); 1613 add_filter( 'should_load_separate_core_block_assets', '__return_false' ); 1614 }, 1615 'inline_size_limit' => 0, 1616 'expected_styles' => array( 1617 'HEAD' => array( 1618 'wp-img-auto-sizes-contain-inline-css', 1619 'early-css', 1620 'early-inline-css', 1621 'wp-emoji-styles-inline-css', 1622 'classic-theme-styles-css', 1623 'global-styles-inline-css', 1624 'normal-css', 1625 'normal-inline-css', 1626 'wp-custom-css', 1627 ), 1628 'BODY' => array( 1629 'late-css', 1630 'late-inline-css', 1631 'core-block-supports-inline-css', 1632 ), 1633 ), 1634 ), 1635 'override_block_library_inline_style_late' => array( 1636 'set_up' => static function () { 1637 add_action( 1638 'enqueue_block_assets', 1639 function (): void { 1640 // This tests what happens when the placeholder comment gets replaced unexpectedly. 1641 wp_styles()->registered['wp-block-library']->extra['after'] = array( '/* OVERRIDDEN! */' ); 1642 } 1643 ); 1644 }, 1645 'inline_size_limit' => 0, 1646 'expected_styles' => array( 1647 'HEAD' => array( 1648 'wp-img-auto-sizes-contain-inline-css', 1649 'early-css', 1650 'early-inline-css', 1651 'wp-emoji-styles-inline-css', 1652 'wp-block-library-css', 1653 'wp-block-library-inline-css', // This contains the "OVERRIDDEN" text. 1654 'wp-block-separator-css', 1655 'global-styles-inline-css', 1656 'core-block-supports-inline-css', 1657 'classic-theme-styles-css', 1658 'normal-css', 1659 'normal-inline-css', 1660 'wp-custom-css', 1661 'late-css', 1662 'late-inline-css', 1663 ), 1664 'BODY' => array(), 1665 ), 1505 1666 ), 1506 1667 ); … … 1511 1672 * 1512 1673 * @ticket 64099 1674 * @covers ::wp_load_classic_theme_block_styles_on_demand 1513 1675 * @covers ::wp_hoist_late_printed_styles 1514 1676 * 1515 1677 * @dataProvider data_wp_hoist_late_printed_styles 1516 1678 */ 1517 public function test_wp_hoist_late_printed_styles( ?Closure $set_up ): void { 1679 public function test_wp_hoist_late_printed_styles( ?Closure $set_up, int $inline_size_limit, array $expected_styles ): void { 1680 switch_theme( 'default' ); 1681 global $wp_styles; 1682 $wp_styles = null; 1683 1684 // Disable the styles_inline_size_limit in order to prevent changes from invalidating the snapshots. 1685 add_filter( 1686 'styles_inline_size_limit', 1687 static function () use ( $inline_size_limit ): int { 1688 return $inline_size_limit; 1689 } 1690 ); 1691 1692 add_filter( 1693 'wp_get_custom_css', 1694 static function () { 1695 return '/* CUSTOM CSS from Customizer */'; 1696 } 1697 ); 1698 1518 1699 if ( $set_up ) { 1519 1700 $set_up(); 1520 1701 } 1521 1702 1522 switch_theme( 'default' ); 1523 1524 // Enqueue a style 1525 wp_enqueue_style( 'early', 'http://example.com/style.css' ); 1703 wp_load_classic_theme_block_styles_on_demand(); 1704 1705 // Ensure that separate core block assets get registered. 1706 register_core_block_style_handles(); 1707 $this->assertTrue( WP_Block_Type_Registry::get_instance()->is_registered( 'core/separator' ), 'Expected the core/separator block to be registered.' ); 1708 1709 // Ensure stylesheet files exist on the filesystem since a build may not have been done. 1710 $this->ensure_style_asset_file_created( 1711 'wp-block-library', 1712 wp_should_load_separate_core_block_assets() ? 'css/dist/block-library/common.css' : 'css/dist/block-library/style.css' 1713 ); 1714 if ( wp_should_load_separate_core_block_assets() ) { 1715 $this->ensure_style_asset_file_created( 'wp-block-separator', 'blocks/separator/style.css' ); 1716 } 1717 $this->assertFalse( wp_is_block_theme(), 'Test is not relevant to block themes (only classic themes).' ); 1718 1719 // Enqueue a style early, before wp_enqueue_scripts. 1720 wp_enqueue_style( 'early', 'https://example.com/style.css' ); 1526 1721 wp_add_inline_style( 'early', '/* EARLY */' ); 1527 1722 1528 wp_hoist_late_printed_styles(); 1529 1530 // Ensure late styles are printed. 1531 add_filter( 'print_late_styles', '__return_false', 1000 ); 1532 $this->assertTrue( apply_filters( 'print_late_styles', true ), 'Expected late style printing to be forced.' ); 1723 // Enqueue a style at the normal spot. 1724 add_action( 1725 'wp_enqueue_scripts', 1726 static function () { 1727 wp_enqueue_style( 'normal', 'https://example.com/normal.css' ); 1728 wp_add_inline_style( 'normal', '/* NORMAL */' ); 1729 } 1730 ); 1731 1732 // Call wp_hoist_late_printed_styles() if wp_load_classic_theme_block_styles_on_demand() queued it up. 1733 if ( has_action( 'wp_template_enhancement_output_buffer_started', 'wp_hoist_late_printed_styles' ) ) { 1734 wp_hoist_late_printed_styles(); 1735 } 1533 1736 1534 1737 // Simulate wp_head. … … 1538 1741 1539 1742 // Enqueue a late style (after wp_head). 1540 wp_enqueue_style( 'late', 'http://example.com/late-style.css', array(), null ); 1541 wp_add_inline_style( 'late', '/* EARLY */' ); 1743 wp_enqueue_style( 'late', 'https://example.com/late-style.css', array(), null ); 1744 wp_add_inline_style( 'late', '/* LATE */' ); 1745 1746 // Simulate the_content(). 1747 $content = apply_filters( 1748 'the_content', 1749 '<!-- wp:separator --><hr class="wp-block-separator has-alpha-channel-opacity"/><!-- /wp:separator -->' 1750 ); 1542 1751 1543 1752 // Simulate footer scripts. … … 1545 1754 1546 1755 // Create a simulated output buffer. 1547 $buffer = '<html><head>' . $head_output . '</head><body><main>Content</main>' . $footer_output . '</body></html>'; 1756 $buffer = '<html lang="en"><head><meta charset="utf-8">' . $head_output . '</head><body><main>' . $content . '</main>' . $footer_output . '</body></html>'; 1757 1758 $placeholder_regexp = '#/\*wp_block_styles_on_demand_placeholder:[a-f0-9]+\*/#'; 1759 if ( has_action( 'wp_template_enhancement_output_buffer_started', 'wp_hoist_late_printed_styles' ) ) { 1760 $this->assertMatchesRegularExpression( $placeholder_regexp, $buffer, 'Expected the placeholder to be present in the buffer.' ); 1761 } 1548 1762 1549 1763 // Apply the output buffer filter. 1550 1764 $filtered_buffer = apply_filters( 'wp_template_enhancement_output_buffer', $buffer ); 1551 1765 1552 $this->assertStringContainsString( '</head>', $ buffer, 'Expected the closing HEAD tag to be in the response.' );1553 1554 $this->assertDoesNotMatchRegularExpression( '#/\*wp_late_styles_placeholder:[a-f0-9-]+\*/#', $filtered_buffer, 'Expected the placeholder to be removed.' );1766 $this->assertStringContainsString( '</head>', $filtered_buffer, 'Expected the closing HEAD tag to be in the response.' ); 1767 1768 $this->assertDoesNotMatchRegularExpression( $placeholder_regexp, $filtered_buffer, 'Expected the placeholder to be removed.' ); 1555 1769 $found_styles = array( 1556 1770 'HEAD' => array(), … … 1570 1784 } 1571 1785 1572 $expected = array( 1573 'early-css', 1574 'early-inline-css', 1575 'late-css', 1576 'late-inline-css', 1577 ); 1578 foreach ( $expected as $style_id ) { 1579 $this->assertContains( $style_id, $found_styles['HEAD'], 'Expected stylesheet with ID to be in the HEAD.' ); 1580 } 1786 /* 1787 * Since new styles could appear at any time and since certain styles leak in from the global scope not being 1788 * properly reset somewhere else in the test suite, we only check that the expected styles are at least present 1789 * and in the same order. When new styles are introduced in core, they may be added to this array as opposed to 1790 * updating the arrays in the data provider, if appropriate. 1791 */ 1792 $ignored_styles = array( 1793 'core-block-supports-duotone-inline-css', 1794 'wp-block-library-theme-css', 1795 'wp-block-template-skip-link-inline-css', 1796 ); 1797 1798 $found_subset_styles = array(); 1799 foreach ( array( 'HEAD', 'BODY' ) as $group ) { 1800 $found_subset_styles[ $group ] = array_values( array_diff( $found_styles[ $group ], $ignored_styles ) ); 1801 } 1802 1581 1803 $this->assertSame( 1582 $expected, 1583 array_values( array_intersect( $found_styles['HEAD'], $expected ) ), 1584 'Expected styles to be printed in the same order.' 1585 ); 1586 $this->assertCount( 0, $found_styles['BODY'], 'Expected no styles to be present in the footer.' ); 1804 $expected_styles, 1805 $found_subset_styles, 1806 'Expected the same styles. Snapshot: ' . self::get_array_snapshot_export( $found_subset_styles ) 1807 ); 1808 } 1809 1810 /** 1811 * Ensures a CSS file is on the filesystem. 1812 * 1813 * This is needed because unit tests may be run without a build step having been done. Something similar can be seen 1814 * elsewhere in tests for the `wp-emoji-loader.js` script: 1815 * 1816 * self::touch( ABSPATH . WPINC . '/js/wp-emoji-loader.js' ); 1817 * 1818 * @param string $handle Style handle. 1819 * @param string $relative_path Relative path to the CSS file in wp-includes. 1820 * 1821 * @throws Exception If the supplied style handle is not registered as expected. 1822 */ 1823 private function ensure_style_asset_file_created( string $handle, string $relative_path ) { 1824 $dependency = wp_styles()->query( $handle ); 1825 if ( ! $dependency ) { 1826 throw new Exception( "The stylesheet for $handle is not registered." ); 1827 } 1828 $dependency->src = includes_url( $relative_path ); 1829 $path = ABSPATH . WPINC . '/' . $relative_path; 1830 if ( ! file_exists( $path ) ) { 1831 $dir = dirname( $path ); 1832 if ( ! file_exists( $dir ) ) { 1833 mkdir( $dir, 0777, true ); 1834 } 1835 file_put_contents( $path, "/* CSS for $handle */" ); 1836 } 1837 wp_style_add_data( $handle, 'path', $path ); 1587 1838 } 1588 1839 … … 1592 1843 1593 1844 $this->assertSame( $expected, $hierarchy, $message ); 1845 } 1846 1847 /** 1848 * Exports PHP array as string formatted as a snapshot for pasting into a data provider. 1849 * 1850 * Unfortunately, `var_export()` always includes array indices even for lists. For example: 1851 * 1852 * var_export( array( 'a', 'b', 'c' ) ); 1853 * 1854 * Results in: 1855 * 1856 * array ( 1857 * 0 => 'a', 1858 * 1 => 'b', 1859 * 2 => 'c', 1860 * ) 1861 * 1862 * This makes it unhelpful when outputting a snapshot to update a unit test. So this function strips out the indices 1863 * to facilitate copy/pasting the snapshot from an assertion error message into the data provider. For example: 1864 * 1865 * array( 1866 * 'a', 1867 * 'b', 1868 * 'c', 1869 * ) 1870 * 1871 * 1872 * @param array $snapshot Snapshot. 1873 * @return string Snapshot export. 1874 */ 1875 private static function get_array_snapshot_export( array $snapshot ): string { 1876 $export = var_export( $snapshot, true ); 1877 $export = preg_replace( '/\barray \($/m', 'array(', $export ); 1878 $export = preg_replace( '/^(\s+)\d+\s+=>\s+/m', '$1', $export ); 1879 $export = preg_replace( '/=> *\n +/', '=> ', $export ); 1880 $export = preg_replace( '/array\(\n\s+\)/', 'array()', $export ); 1881 return preg_replace_callback( 1882 '/(^ +)/m', 1883 static function ( $matches ) { 1884 return str_repeat( "\t", strlen( $matches[0] ) / 2 ); 1885 }, 1886 $export 1887 ); 1594 1888 } 1595 1889
Note: See TracChangeset
for help on using the changeset viewer.