test-helpers.js (9266B)
1 (function() { 2 var next_cache_index = 1; 3 4 // Returns a promise that resolves to a newly created Cache object. The 5 // returned Cache will be destroyed when |test| completes. 6 function create_temporary_cache(test) { 7 var uniquifier = String(++next_cache_index); 8 var cache_name = self.location.pathname + '/' + uniquifier; 9 10 test.add_cleanup(function() { 11 self.caches.delete(cache_name); 12 }); 13 14 return self.caches.delete(cache_name) 15 .then(function() { 16 return self.caches.open(cache_name); 17 }); 18 } 19 20 self.create_temporary_cache = create_temporary_cache; 21 })(); 22 23 // Runs |test_function| with a temporary unique Cache passed in as the only 24 // argument. The function is run as a part of Promise chain owned by 25 // promise_test(). As such, it is expected to behave in a manner identical (with 26 // the exception of the argument) to a function passed into promise_test(). 27 // 28 // E.g.: 29 // cache_test(function(cache) { 30 // // Do something with |cache|, which is a Cache object. 31 // }, "Some Cache test"); 32 function cache_test(test_function, description) { 33 promise_test(function(test) { 34 return create_temporary_cache(test) 35 .then(function(cache) { return test_function(cache, test); }); 36 }, description); 37 } 38 39 // A set of Request/Response pairs to be used with prepopulated_cache_test(). 40 var simple_entries = [ 41 { 42 name: 'a', 43 request: new Request('http://example.com/a'), 44 response: new Response('') 45 }, 46 47 { 48 name: 'b', 49 request: new Request('http://example.com/b'), 50 response: new Response('') 51 }, 52 53 { 54 name: 'a_with_query', 55 request: new Request('http://example.com/a?q=r'), 56 response: new Response('') 57 }, 58 59 { 60 name: 'A', 61 request: new Request('http://example.com/A'), 62 response: new Response('') 63 }, 64 65 { 66 name: 'a_https', 67 request: new Request('https://example.com/a'), 68 response: new Response('') 69 }, 70 71 { 72 name: 'a_org', 73 request: new Request('http://example.org/a'), 74 response: new Response('') 75 }, 76 77 { 78 name: 'cat', 79 request: new Request('http://example.com/cat'), 80 response: new Response('') 81 }, 82 83 { 84 name: 'catmandu', 85 request: new Request('http://example.com/catmandu'), 86 response: new Response('') 87 }, 88 89 { 90 name: 'cat_num_lives', 91 request: new Request('http://example.com/cat?lives=9'), 92 response: new Response('') 93 }, 94 95 { 96 name: 'cat_in_the_hat', 97 request: new Request('http://example.com/cat/in/the/hat'), 98 response: new Response('') 99 }, 100 101 { 102 name: 'non_2xx_response', 103 request: new Request('http://example.com/non2xx'), 104 response: new Response('', {status: 404, statusText: 'nope'}) 105 }, 106 107 { 108 name: 'error_response', 109 request: new Request('http://example.com/error'), 110 response: Response.error() 111 }, 112 ]; 113 114 // A set of Request/Response pairs to be used with prepopulated_cache_test(). 115 // These contain a mix of test cases that use Vary headers. 116 var vary_entries = [ 117 { 118 name: 'vary_cookie_is_cookie', 119 request: new Request('http://example.com/c', 120 {headers: {'Cookies': 'is-for-cookie'}}), 121 response: new Response('', 122 {headers: {'Vary': 'Cookies'}}) 123 }, 124 125 { 126 name: 'vary_cookie_is_good', 127 request: new Request('http://example.com/c', 128 {headers: {'Cookies': 'is-good-enough-for-me'}}), 129 response: new Response('', 130 {headers: {'Vary': 'Cookies'}}) 131 }, 132 133 { 134 name: 'vary_cookie_absent', 135 request: new Request('http://example.com/c'), 136 response: new Response('', 137 {headers: {'Vary': 'Cookies'}}) 138 } 139 ]; 140 141 // Run |test_function| with a Cache object and a map of entries. Prior to the 142 // call, the Cache is populated by cache entries from |entries|. The latter is 143 // expected to be an Object mapping arbitrary keys to objects of the form 144 // {request: <Request object>, response: <Response object>}. Entries are 145 // serially added to the cache in the order specified. 146 // 147 // |test_function| should return a Promise that can be used with promise_test. 148 function prepopulated_cache_test(entries, test_function, description) { 149 cache_test(function(cache) { 150 var p = Promise.resolve(); 151 var hash = {}; 152 entries.forEach(function(entry) { 153 hash[entry.name] = entry; 154 p = p.then(function() { 155 return cache.put(entry.request.clone(), entry.response.clone()) 156 .catch(function(e) { 157 assert_unreached( 158 'Test setup failed for entry ' + entry.name + ': ' + e 159 ); 160 }); 161 }); 162 }); 163 return p 164 .then(function() { 165 assert_equals(Object.keys(hash).length, entries.length); 166 }) 167 .then(function() { 168 return test_function(cache, hash); 169 }); 170 }, description); 171 } 172 173 // Helper for testing with Headers objects. Compares Headers instances 174 // by serializing |expected| and |actual| to arrays and comparing. 175 function assert_header_equals(actual, expected, description) { 176 assert_class_string(actual, "Headers", description); 177 var header; 178 var actual_headers = []; 179 var expected_headers = []; 180 for (header of actual) 181 actual_headers.push(header[0] + ": " + header[1]); 182 for (header of expected) 183 expected_headers.push(header[0] + ": " + header[1]); 184 assert_array_equals(actual_headers, expected_headers, 185 description + " Headers differ."); 186 } 187 188 // Helper for testing with Response objects. Compares simple 189 // attributes defined on the interfaces, as well as the headers. It 190 // does not compare the response bodies. 191 function assert_response_equals(actual, expected, description) { 192 assert_class_string(actual, "Response", description); 193 ["type", "url", "status", "ok", "statusText"].forEach(function(attribute) { 194 assert_equals(actual[attribute], expected[attribute], 195 description + " Attributes differ: " + attribute + "."); 196 }); 197 assert_header_equals(actual.headers, expected.headers, description); 198 } 199 200 // Assert that the two arrays |actual| and |expected| contain the same 201 // set of Responses as determined by assert_response_equals. The order 202 // is not significant. 203 // 204 // |expected| is assumed to not contain any duplicates. 205 function assert_response_array_equivalent(actual, expected, description) { 206 assert_true(Array.isArray(actual), description); 207 assert_equals(actual.length, expected.length, description); 208 expected.forEach(function(expected_element) { 209 // assert_response_in_array treats the first argument as being 210 // 'actual', and the second as being 'expected array'. We are 211 // switching them around because we want to be resilient 212 // against the |actual| array containing duplicates. 213 assert_response_in_array(expected_element, actual, description); 214 }); 215 } 216 217 // Asserts that two arrays |actual| and |expected| contain the same 218 // set of Responses as determined by assert_response_equals(). The 219 // corresponding elements must occupy corresponding indices in their 220 // respective arrays. 221 function assert_response_array_equals(actual, expected, description) { 222 assert_true(Array.isArray(actual), description); 223 assert_equals(actual.length, expected.length, description); 224 actual.forEach(function(value, index) { 225 assert_response_equals(value, expected[index], 226 description + " : object[" + index + "]"); 227 }); 228 } 229 230 // Equivalent to assert_in_array, but uses assert_response_equals. 231 function assert_response_in_array(actual, expected_array, description) { 232 assert_true(expected_array.some(function(element) { 233 try { 234 assert_response_equals(actual, element); 235 return true; 236 } catch (e) { 237 return false; 238 } 239 }), description); 240 } 241 242 // Helper for testing with Request objects. Compares simple 243 // attributes defined on the interfaces, as well as the headers. 244 function assert_request_equals(actual, expected, description) { 245 assert_class_string(actual, "Request", description); 246 ["url"].forEach(function(attribute) { 247 assert_equals(actual[attribute], expected[attribute], 248 description + " Attributes differ: " + attribute + "."); 249 }); 250 assert_header_equals(actual.headers, expected.headers, description); 251 } 252 253 // Asserts that two arrays |actual| and |expected| contain the same 254 // set of Requests as determined by assert_request_equals(). The 255 // corresponding elements must occupy corresponding indices in their 256 // respective arrays. 257 function assert_request_array_equals(actual, expected, description) { 258 assert_true(Array.isArray(actual), description); 259 assert_equals(actual.length, expected.length, description); 260 actual.forEach(function(value, index) { 261 assert_request_equals(value, expected[index], 262 description + " : object[" + index + "]"); 263 }); 264 } 265 266 // Deletes all caches, returning a promise indicating success. 267 function delete_all_caches() { 268 return self.caches.keys() 269 .then(function(keys) { 270 return Promise.all(keys.map(self.caches.delete.bind(self.caches))); 271 }); 272 }