Testing Your Offline Applications

By Rob Gravelle


As great as the AppCache is, its use of the Manifest file can be unforgiving, to say the least. When things go wrong, no errors are displayed, everything looks fine while online, but then, should the connection go down, nothing happens! Under such circumstances, your offline applications need to be thoroughly tested before making them available to the general public. The question is how to do that. Today, we'll be answering that question by looking at some strategies for testing your offline applications, both locally and in a production environment. If you haven't already, I would suggest that you read the first two articles in this series, The AppCache in Action and Build an Offline HTML5 Web Application.

Delivering the (Manifest) Goods

Perhaps the trickiest part of setting up the AppCache in production is that the manifest file must be served up with a special mime-type of "text/cache-manifest". This makes sense when you stop and think about it; how else would the browser recognize the manifest file? The file name can be anything you like so that's out of the question.

It's up to the developer to configure the server to send the correct mime-type along with the Cache Manifest. There are a few ways to do it, a lot of them being tied to the server vendor. For instance, if you are using Apache, you have to add the following entry to the .htaccess file:

AddType     text/cache-manifest     .manifest

Other developers have relied on server-side languages to set the mime-type. Usually there is a command to set it, such as Java's setContentType() method:


While testing my Offline app, I came across a rather novel approach (at least it was novel to me!). If your Web app is Java-based, you can set the mime-type in the web.xml file. The tag is called "mime-mapping". It includes the extension and the associated content type:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>Good Food Talks</display-name>

Once you've uploaded the Manifest file and have configured the server to serve it as "text/cache-manifest" content, the next time that you bring up the page containing the manifest attribute up in your browser (online of course!), you'll probably be greeted with some sort of security dialog by your browser. Here's what I received in Firefox:

Once you allow the browser to cache the files, you can try again without a connection. The easiest way to do that is to simply turn off your server. Then, when you connect to your site, the browser will spin its wheels for a bit while it tries to connect, then finally, the cached resources should appear.

Google Chrome is a good choice for conducting your tests on, because the javascript console displays messages about the "Application Cache" loading. It will also inform you of any bad links in your cache.manifest file. Once your cacheable web page comes up in the browser, click Refresh to re-test your manifest links.

iPad and Safari are also a good combination. Add your application start page to your Home Screen, then you can test your Offline app by turning on Airplane mode in Settings and then click the icon to see if you can still launch your app.

The View From Chrome

Chrome is especially well suited for testing the efficacy of your Manifest file in downloading resources for offline viewing, thanks to its multiple tools designed expressly for that purpose.

The JavaScript Console & AppCache Events

In Chrome, you can see the files being downloaded in real time from the JavaScript console. In other browsers, similar information can be produced using AppCache events. Insert some JavaScript code in your HTML page like the following to monitor the downloading of your referenced files:

//Convenience array of status values
var cacheStatusValues = [];
 cacheStatusValues[0] = 'uncached';
 cacheStatusValues[1] = 'idle';
 cacheStatusValues[2] = 'checking';
 cacheStatusValues[3] = 'downloading';
 cacheStatusValues[4] = 'updateready';
 cacheStatusValues[5] = 'obsolete';

 // Listeners for all possible events
 var cache = window.applicationCache;
 cache.addEventListener('cached', logEvent, false);
 cache.addEventListener('checking', logEvent, false);
 cache.addEventListener('downloading', logEvent, false);
 cache.addEventListener('error', logEvent, false);
 cache.addEventListener('noupdate', logEvent, false);
 cache.addEventListener('obsolete', logEvent, false);
 cache.addEventListener('progress', logEvent, false);
 cache.addEventListener('updateready', logEvent, false);

 // Log every event to the console
 function logEvent(e) {
     var online, status, type, message;
     online = (isOnline()) ? 'yes' : 'no';
     status = cacheStatusValues[cache.status];
     type = e.type;
     message = 'online: ' + online;
     message+= ', event: ' + type;
     message+= ', status: ' + status;
     if (type == 'error' && navigator.onLine) {
         message+= ' There was an unknown error, check your Cache Manifest.';

 function log(s) {

 function isOnline() {
     return navigator.onLine;

 if (!jQuery('html').attr('manifest')) {
    log('No Cache Manifest listed on the  tag.')

 // Swap in newly download files when update is ready
 cache.addEventListener('updateready', function(e){
         // Don't perform "swap" if this is the first cache
         if (cacheStatusValues[cache.status] != 'idle') {
             log('Swapped/updated the Cache Manifest.');
 , false);

 // These two functions check for updates to the manifest file
 function checkForUpdates(){
 function autoCheckForUpdates(){
     setInterval(function(){cache.update()}, 10000);

The following screenshot shows the JS console output in Chrome. The entries containing numbers "(from x to x)" are from Chrome, while the others were produced by our JavaScript code:

Appcache Internals

Typing "chrome://appcache-internals/" in the Address Box will show you exactly what's been downloaded to the AppCache. Here is what a typical stats page might look like with the entries displayed:

Manifest: http://localhost:8080/DynamicHTML5WebProject/GoodFoodTalks.manifest

Remove View Entries

  • Size: 364 kB
  • Creation Time: Tuesday, September 17, 2013 11:13:56 AM


It's imperative that you thoroughly test your Offline Applications before deploying them to production because, as I alluded to at the start of this article, the unforgiving nature of the Manifest file can cause one little typo to knock out all of your offline functionality.

If you enjoyed this article, please contribute to Rob's rock star aspirations by purchasing one of Rob's cover or original songs from iTunes.com for only 0.99 cents each.

Rob Gravelle resides in Ottawa, Canada, and is the founder of GravelleWebDesign.com. Rob has built systems for Intelligence-related organizations such as Canada Border Services, CSIS as well as for numerous commercial businesses. Email Rob to receive a free estimate on your software project.

In his spare time, Rob has become an accomplished guitar player, and has released several CDs. His band, Ivory Knight, was rated as one Canada's top hard rock and metal groups by Brave Words magazine (issue #92).

Rob uses and recommends MochaHost, which provides Web Hosting at $1.95 per month, 2 LifeTime Free Domains, and 6 Months Free!

  • Web Development Newsletter Signup

    Invalid email
    You have successfuly registered to our newsletter.
Thanks for your registration, follow us on our social networks to keep up-to-date