Skip to content

Commit

Permalink
Merge pull request #697 from GoogleChromeLabs/feature/438-reload-offl…
Browse files Browse the repository at this point in the history
…ine-page

Add page reloading in offline.php templates
  • Loading branch information
westonruter authored Feb 24, 2022
2 parents 9806304 + 661946f commit 22b997f
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 0 deletions.
66 changes: 66 additions & 0 deletions tests/test-template.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php
/**
* Tests for template.php
*
* @package PWA
*/

use Yoast\WPTestUtils\WPIntegration\TestCase;

/**
* Tests for template.php
*/
class Test_Template extends TestCase {
/**
* Test if function adding script on GET method, is_offline() or is_500 is true
*
* @covers ::wp_service_worker_offline_page_reload()
*/
public function test_wp_service_worker_offline_page_reload() {
$this->assertEquals( 10, has_action( 'wp_footer', 'wp_service_worker_offline_page_reload' ) );
$this->assertEquals( 10, has_action( 'error_footer', 'wp_service_worker_offline_page_reload' ) );

// Check when method is GET but not offline or 500.
$actual_script = wp_service_worker_offline_page_reload();
$this->assertEquals( $_SERVER['REQUEST_METHOD'], 'GET' );
$this->assertFalse( is_offline() );
$this->assertFalse( is_500() );
$this->assertEmpty( $actual_script );

// Check if script is added when offline.
$error_template_url = add_query_arg( 'wp_error_template', 'offline', home_url( '/', 'relative' ) );
$this->go_to( $error_template_url );

ob_start();
wp_service_worker_offline_page_reload();
$actual_script = ob_get_clean();
$this->assertEquals( $_SERVER['REQUEST_METHOD'], 'GET' );
$this->assertTrue( is_offline() );
$this->assertFalse( is_500() );
$this->assertStringContainsString( '<script type="module">', $actual_script );
$this->assertStringContainsString( 'await fetch(location.href, {method: \'HEAD\'})', $actual_script );

// Check if script is added when 500.
$error_template_url = add_query_arg( 'wp_error_template', '500', home_url( '/', 'relative' ) );
$this->go_to( $error_template_url );

ob_start();
wp_service_worker_offline_page_reload();
$actual_script = ob_get_clean();
$this->assertEquals( $_SERVER['REQUEST_METHOD'], 'GET' );
$this->assertFalse( is_offline() );
$this->assertTrue( is_500() );
$this->assertStringContainsString( '<script type="module">', $actual_script );
$this->assertStringContainsString( 'await fetch(location.href, {method: \'HEAD\'})', $actual_script );

$this->go_to( home_url( '/', 'relative' ) );

// Check when method is not GET.
$_SERVER['REQUEST_METHOD'] = 'POST';
$actual_script = wp_service_worker_offline_page_reload();
$this->assertEquals( $_SERVER['REQUEST_METHOD'], 'POST' );
$this->assertFalse( is_offline() );
$this->assertFalse( is_500() );
$this->assertEmpty( $actual_script );
}
}
52 changes: 52 additions & 0 deletions wp-includes/template.php
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,55 @@ function wp_service_worker_error_details_template( $output = '' ) {
function wp_service_worker_error_message_placeholder() {
echo '<p><!--WP_SERVICE_WORKER_ERROR_MESSAGE--></p>';
}

/**
* Reload the offline page and check if user comes online.
*
* @since 0.7
*/
function wp_service_worker_offline_page_reload() {
if ( isset( $_SERVER['REQUEST_METHOD'] ) && 'GET' !== $_SERVER['REQUEST_METHOD'] ) {
return;
}

if ( ! is_offline() && ! is_500() ) {
return;
}

?>
<script type="module">
/**
* Listen to changes in the network state, reload when online.
* This handles the case when the device is completely offline.
*/
window.addEventListener('online', () => {
window.location.reload();
});

// Create a counter to implement exponential backoff.
let count = 0;

/**
* Check if the server is responding and reload the page if it is.
* This handles the case when the device is online, but the server is offline or misbehaving.
*/
async function checkNetworkAndReload() {
try {
const response = await fetch(location.href, {method: 'HEAD'});
// Verify we get a valid response from the server
if (response.status >= 200 && response.status < 500) {
window.location.reload();
return;
}
} catch {
// Unable to connect so do nothing.
}
window.setTimeout(checkNetworkAndReload, Math.pow(2, count++) * 2500);
}
checkNetworkAndReload();
</script>
<?php
}

add_action( 'wp_footer', 'wp_service_worker_offline_page_reload' );
add_action( 'error_footer', 'wp_service_worker_offline_page_reload' );

0 comments on commit 22b997f

Please sign in to comment.