xmlhttprequest-event-order.js (2927B)
1 (function(global) { 2 var recorded_xhr_events = []; 3 4 function record_xhr_event(e) { 5 var prefix = e.target instanceof XMLHttpRequestUpload ? "upload." : ""; 6 recorded_xhr_events.push((prefix || "") + e.type + "(" + e.loaded + "," + e.total + "," + e.lengthComputable + ")"); 7 } 8 9 global.prepare_xhr_for_event_order_test = function(xhr) { 10 xhr.addEventListener("readystatechange", function(e) { 11 recorded_xhr_events.push(xhr.readyState); 12 }); 13 var events = ["loadstart", "progress", "abort", "timeout", "error", "load", "loadend"]; 14 for(var i=0; i<events.length; ++i) { 15 xhr.addEventListener(events[i], record_xhr_event); 16 } 17 if ("upload" in xhr) { 18 for(var i=0; i<events.length; ++i) { 19 xhr.upload.addEventListener(events[i], record_xhr_event); 20 } 21 } 22 } 23 24 function getNextEvent(arr) { 25 var event = { str: arr.shift() }; 26 27 // we can only handle strings, numbers (readystates) and undefined 28 if (event.str === undefined) { 29 return event; 30 } 31 32 if (typeof event.str !== "string") { 33 if (Number.isInteger(event.str)) { 34 event.state = event.str; 35 event.str = "readystatechange(" + event.str + ")"; 36 } else { 37 throw "Test error: unexpected event type " + event.str; 38 } 39 } 40 41 // parse out the general type, loaded and total values 42 var type = event.type = event.str.split("(")[0].split(".").pop(); 43 var loadedAndTotal = event.str.match(/.*\((\d+),(\d+),(true|false)\)/); 44 if (loadedAndTotal) { 45 event.loaded = parseInt(loadedAndTotal[1]); 46 event.total = parseInt(loadedAndTotal[2]); 47 event.lengthComputable = loadedAndTotal[3] == "true"; 48 } 49 50 return event; 51 } 52 53 global.assert_xhr_event_order_matches = function(expected) { 54 var recorded = recorded_xhr_events; 55 var lastRecordedLoaded = -1; 56 while(expected.length && recorded.length) { 57 var currentExpected = getNextEvent(expected), 58 currentRecorded = getNextEvent(recorded); 59 60 // skip to the last progress event if we've hit one (note the next 61 // event after a progress event should be a LOADING readystatechange, 62 // if there are multiple progress events in a row). 63 while (recorded.length && currentRecorded.type == "progress" && 64 parseInt(recorded) === 3) { 65 assert_greater_than(currentRecorded.loaded, lastRecordedLoaded, 66 "progress event 'loaded' values must only increase"); 67 lastRecordedLoaded = currentRecorded.loaded; 68 } 69 if (currentRecorded.type == "loadend") { 70 recordedProgressCount = 0; 71 lastRecordedLoaded = -1; 72 } 73 74 assert_equals(currentRecorded.str, currentExpected.str); 75 } 76 if (recorded.length) { 77 throw "\nUnexpected extra events: " + recorded.join(", "); 78 } 79 if (expected.length) { 80 throw "\nExpected more events: " + expected.join(", "); 81 } 82 } 83 }(this));