resource_timing_main_test.html (12487B)
1 <!-- 2 Any copyright is dedicated to the Public Domain. 3 http://creativecommons.org/publicdomain/zero/1.0/ 4 --> 5 6 <!-- 7 This file contains test for the Resource Timing and Performance Timeline APIs. 8 The test starts by checking that all the entries were added to the performance 9 object. 10 The next step is to check that the "performance" object and its "getEntries()" 11 methods are available. We check all the 3 methods: getEntries, 12 getEntriesByName() and getEntriesByType(). 13 14 As a next step, we check that the entries contain the correct information 15 ("checkEntries()" method). 16 The test checks that the entries contain all the required members, that the 17 timings are sorted properly and that the entries were returned in 18 chronological order with respect to startTime. In "checkEntries()", it is also 19 checked if the order of the entries is the expected order (the expected order 20 is hard-coded here). 21 The last test from the "checkEntries()" method will verify the iframe case: 22 the iframe must be added as an entry to this window's performance object, 23 while the image from the iframe should not be added here. 24 25 Next tests will check the Performance API extensions introduced by the 26 resource timing: window.performance.setResourceTimingBufferSize(1) and 27 window.performance.clearResourceTimings(); 28 29 The last tests will verify that the xhr resources are also added as entries 30 to our performance object. 31 32 Meanwhile, the iframe from the page will get loaded 33 (resource_timing_iframe.html). 34 The iframe contains a second script that will do some tests, as well, plus 35 an image - its own resource. 36 The script from the iframe will check that the iframe itself was not added 37 as an entry (to itself). Also, it will check that its image was added as 38 entry to the iframe's performance object. 39 The last check is a double check: check that no subdocuments were added as 40 entries for this iframe's performance object. 41 The parent's (this window) "ok_wrapper()" method will be called once the tests 42 are completed. 43 --> 44 45 <!DOCTYPE html> 46 <html> 47 <head> 48 <meta charset="utf-8"> 49 <link rel="stylesheet" href="/tests/SimpleTest/test.css?resource-timing-main-test"/> 50 <script type="application/javascript"> 51 52 var mainWindowTestsDone = false; 53 var iframeTestsDone = false; 54 55 function ok(cond, message) { 56 window.opener.ok(cond, message) 57 } 58 59 function is(received, expected, message) { 60 window.opener.is(received, expected, message); 61 } 62 63 function isnot(received, notExpected, message) { 64 window.opener.isnot(received, notExpected, message); 65 } 66 67 var bufferFullCounter = 0; 68 const expectedBufferFullEvents = 1; 69 70 var allResources = { 71 "http://mochi.test:8888/tests/SimpleTest/test.css?resource-timing-main-test": "link", 72 "http://mochi.test:8888/tests/image/test/mochitest/blue.png" : "img", 73 "http://mochi.test:8888/tests/image/test/mochitest/red.png" : "object", 74 "http://mochi.test:8888/tests/image/test/mochitest/big.png" : "embed", 75 "http://mochi.test:8888/tests/dom/tests/mochitest/general/resource_timing_iframe.html" : "iframe"}; 76 77 window.onload = function() { 78 ok(!!window.performance, "Performance object should exist"); 79 ok(!!window.performance.getEntries, "Performance.getEntries() should exist"); 80 ok(!!window.performance.getEntriesByName, "Performance.getEntriesByName() should exist"); 81 ok(!!window.performance.getEntriesByType, "Performance.getEntriesByType() should exist"); 82 83 window.performance.onresourcetimingbufferfull = function() { 84 bufferFullCounter += 1; 85 } 86 87 is(window.performance.getEntriesByType("resource").length, Object.keys(allResources).length, "Performance.getEntriesByType() returned wrong number of entries."); 88 89 checkStringify(window.performance.getEntriesByType("resource")[0]); 90 91 ok(!!window.performance.getEntriesByType("resource").length, 92 "Performance.getEntriesByType() should return some results"); 93 ok(!!window.performance.getEntriesByName("http://mochi.test:8888/tests/image/test/mochitest/blue.png").length, 94 "Performance.getEntriesByName() should return some results"); 95 96 // Checks that two calls for "getEntriesByType()" return a different array with the same 97 // entries. 98 isnot(window.performance.getEntriesByType("resource"), window.performance.getEntriesByType("resource"), 99 "getEntriesByType() should return a different array object every time."); 100 ok(function (array1, array2) { 101 if (array1.length != array2.length) { 102 return false; 103 } 104 for (var i = 0 ; i < array1.length ; i++) { 105 if (array1[i] !== array2[i]) { 106 return false; 107 } 108 } 109 return true; 110 }(window.performance.getEntriesByType("resource"), window.performance.getEntriesByType("resource")), 111 "The arrays should have the same entries."); 112 113 checkEntries(window.performance.getEntriesByType("resource")); 114 115 window.performance.setResourceTimingBufferSize(1); 116 is(window.performance.getEntriesByType("resource").length, Object.keys(allResources).length, "No entries should be " + 117 "removed when setResourceTimingBufferSize is called."); 118 119 window.performance.setResourceTimingBufferSize(4); 120 is(window.performance.getEntriesByType("resource").length, Object.keys(allResources).length, "No entries should be " + 121 "removed when setResourceTimingBufferSize is called."); 122 123 window.performance.setResourceTimingBufferSize(1); 124 window.performance.clearResourceTimings(); 125 is(window.performance.getEntriesByType("resource").length, 0, "All the entries should " + 126 "be removed when when clearResourceTimings is being called."); 127 128 makeXhr("test-data.json", firstCheck); 129 } 130 131 function checkStringify(entry) { 132 var object = JSON.parse(JSON.stringify(entry)); 133 var keys = ["initiatorType","redirectStart","redirectEnd","fetchStart", 134 "domainLookupStart","domainLookupEnd","connectStart","connectEnd", 135 "secureConnectionStart","requestStart","responseStart","responseEnd", 136 "name","entryType","startTime","duration"]; 137 for (var i in keys) { 138 ok(keys[i] in object, "The serialization should contain key: "+keys[i]); 139 } 140 } 141 142 function checkEntries(anEntryList) { 143 // Check that all the entries have all the properties. 144 for (var i = 0 ; i < anEntryList.length ; i++) { 145 var entry = anEntryList[i]; 146 147 ok(!!entry, "PerformanceEntry should not be null"); 148 ok(!!entry.name, "PerformanceEntry.name should be valid."); 149 ok(entry.startTime > 0, "PerformanceEntry.startTime should be grater than 0"); 150 151 // The entries list should be in chronological order with respect to startTime 152 if (i > 0) { 153 ok(anEntryList[i - 1].startTime <= anEntryList[i].startTime, 154 "Entries list should be in chronological order with respect to startTime."); 155 } 156 157 // Check that each entry has all the properties and that the timings were 158 // returned in the expected order. 159 if ("initiatorType" in entry) { 160 ok("redirectStart" in entry, "PerformanceEntry.redirectStart should be part of PerformanceEntry"); 161 ok("redirectEnd" in entry, "PerformanceEntry.redirectEnd should be part of PerformanceEntry"); 162 ok("fetchStart" in entry, "PerformanceEntry.fetchStart should be part of PerformanceEntry"); 163 ok("domainLookupStart" in entry, "PerformanceEntry.domainLookupStart should be part of PerformanceEntry"); 164 ok("domainLookupEnd" in entry, "PerformanceEntry.domainLookupEnd should be part of PerformanceEntry"); 165 ok("connectStart" in entry, "PerformanceEntry.connectStart should be part of PerformanceEntry"); 166 ok("connectEnd" in entry, "PerformanceEntry.connectEnd should be part of PerformanceEntry"); 167 ok("secureConnectionStart" in entry, "PerformanceEntry.secureConnectionStart should be part of PerformanceEntry"); 168 ok("requestStart" in entry, "PerformanceEntry.requestStart should be part of PerformanceEntry"); 169 ok("responseStart" in entry, "PerformanceEntry.responseStart should be part of PerformanceEntry"); 170 ok("responseEnd" in entry, "PerformanceEntry.responseEnd should be part of PerformanceEntry"); 171 172 // Check that timings are in proper order 173 sequence = ['startTime', 'redirectStart', 'redirectEnd', 'fetchStart', 174 'domainLookupStart', 'domainLookupEnd', 'connectStart', 175 'connectEnd', 'requestStart', 'responseStart', 'responseEnd']; 176 for (var j = 1; j < sequence.length; ++j) { 177 var prop = sequence[j]; 178 var prevProp = sequence[j-1]; 179 if (prop == 'redirectStart' && entry[prop] == 0) 180 continue; 181 if (prop == 'redirectEnd' && entry[prop] == 0) 182 continue; 183 ok(entry[prevProp] <= entry[prop], 184 ['Expected ', prevProp, ' to happen before ', prop, 185 ', got ', prevProp, ' = ', entry[prevProp], 186 ', ', prop, ' = ', entry[prop]].join('')); 187 } 188 } 189 } 190 191 // Check that the entries have the expected initiator type. We can't check 192 // the order (the order might depend on the platform the tests are running). 193 for (resourceName in allResources) { 194 // Check that we have a resource with the specific name. 195 namedEntries = window.performance.getEntriesByName(resourceName); 196 ok (!!namedEntries && (namedEntries.length == 1), 197 "An entry with the name '" + resourceName + "' should be available"); 198 199 if (!namedEntries.length) { 200 continue; 201 } 202 203 // Double check for the entry name. 204 is (namedEntries[0].name, resourceName, "The resource name is invalid"); 205 206 // Check the initiator type. 207 is (namedEntries[0].initiatorType, allResources[resourceName], 208 "The initiator type for " + resourceName + " is invalid"); 209 } 210 211 // Check that the iframe's image was NOT added as an entry to this window's performance entry. 212 ok(!window.performance.getEntriesByName("http://mochi.test:8888/tests/image/test/mochitest/damon.jpg").length, 213 "http://mochi.test:8888/tests/image/test/mochitest/damon.jpg should be a valid entry name"); 214 } 215 216 function firstCheck() { 217 is(window.performance.getEntriesByType("resource").length, 1, "The first xhr entry was not added."); 218 is(window.performance.getEntriesByType("resource")[0].initiatorType, "xmlhttprequest", 219 "The initiatorType is incorrect for this entry"); 220 makeXhr("test-data2.json", secondCheck); 221 } 222 223 function secondCheck() { 224 // Since the buffer max size was set to '1', 'peformance.getEntriesByType()' should 225 // return only '1' entry (first xhr results). 226 is(window.performance.getEntriesByType("resource").length, 1, "The second xhr entry should not be " + 227 "returned since the buffer size was set to 1."); 228 isnot(window.performance.getEntriesByType("resource")[0].name, "http://mochi.test:8888/tests/dom/tests/mochitest/general/test-data2.json", 229 "We returned the second xhr instead of the first one"); 230 finishTest(); 231 } 232 233 function finishTest() { 234 // Check if all the tests are completed. 235 SpecialPowers.executeSoon(function () { 236 if (iframeTestsDone) { 237 is(bufferFullCounter, expectedBufferFullEvents, "onresourcetimingbufferfull called a wrong number of times"); 238 window.opener.finishTests(); 239 } else { 240 mainWindowTestsDone = true; 241 } 242 }, window); 243 } 244 245 function makeXhr(aUrl, aCallback) { 246 var xmlhttp = new XMLHttpRequest(); 247 xmlhttp.onload = aCallback; 248 xmlhttp.open("get", aUrl, true); 249 xmlhttp.send(); 250 } 251 252 function checkArraysHaveSameElementsInSameOrder(array1, array2) { 253 if (array1.length != array2.length) { 254 return false; 255 } 256 for (var i = 0 ; i < array1.length ; i++) { 257 if (array1[i] !== array2[i]) { 258 return false; 259 } 260 } 261 return true; 262 } 263 264 function iframeTestsCompleted() { 265 if (mainWindowTestsDone) { 266 is(bufferFullCounter, expectedBufferFullEvents, "onresourcetimingbufferfull called a wrong number of times"); 267 window.opener.finishTests(); 268 } 269 else { 270 iframeTestsDone = true; 271 } 272 } 273 274 </script> 275 </head> 276 <body> 277 <a target="_blank" 278 href="https://bugzilla.mozilla.org/show_bug.cgi?id=822480" 279 title="Add resource timing API."> 280 Bug #822480 - Add in the Resource Timing API 281 </a> 282 <p id="display"></p> 283 <div id="content"> 284 <img src="http://mochi.test:8888/tests/image/test/mochitest/blue.png"> 285 <object data="http://mochi.test:8888/tests/image/test/mochitest/red.png" type="image/png"></object> 286 <embed src="http://mochi.test:8888/tests/image/test/mochitest/big.png" type="image/png"/> 287 <iframe sandbox="allow-same-origin allow-scripts" id="if_2" src="resource_timing_iframe.html" height="10" width="10"></iframe> 288 </div> 289 </body> 290 </html>