LCOV - code coverage report
Current view: top level - test/wpt/xhr - xmlhttprequest-event-order.js (source / functions) Hit Total Coverage
Test: lcov.info Lines: 182 199 91.5 %
Date: 2024-12-07 00:20:21 Functions: 5 6 83.3 %
Branches: 31 40 77.5 %

           Branch data     Line data    Source code
       1            [ + ]:         17 : import assert from 'node:assert';
       2                 :         17 : 
       3                 :         17 : const recorded_xhr_events = [];
       4                 :         17 : const actual_xhr_events = [];
       5                 :         17 : 
       6            [ + ]:         17 : const record_xhr_event = (e) => {
       7       [ + ][ + ]:         33 :         const prefix = e.target.constructor.name === 'XMLHttpRequestUpload' ? 'upload.' : '';
       8            [ + ]:         33 :         const event = (prefix || '') + e.type + '(' + e.loaded + ',' + e.total + ',' + e.lengthComputable + ')';
       9                 :         33 : 
      10                 :         33 :         recorded_xhr_events.push(event);
      11                 :         33 :         actual_xhr_events.push(event);
      12                 :         33 : }
      13                 :         17 : 
      14       [ + ][ + ]:         17 : const getNextEvent = (arr) => {
      15                 :         92 :         let event = {
      16                 :         92 :                 str: arr.shift()
      17                 :         92 :         };
      18                 :         92 : 
      19                 :         92 :         // we can only handle strings, numbers (readystates) and undefined
      20       [ - ][ - ]:         92 :         if(event.str === undefined){
      21                 :          0 :                 return event;
      22                 :          0 :         }
      23                 :         92 : 
      24       [ + ][ + ]:         92 :         if(typeof event.str !== 'string'){
      25                 :         30 : 
      26                 :         30 :                 if(/^\d+$/.test(event.str)){
      27                 :         30 :                         event.state = event.str;
      28                 :         30 :                         event.str = `readystatechange(${event.str})`;
      29       [ - ][ - ]:         30 :                 }
      30                 :          0 :                 else{
      31                 :          0 :                         throw `Test error: unexpected event type ${event.str}`;
      32                 :          0 :                 }
      33                 :         30 :         }
      34                 :         92 : 
      35                 :         92 :         // parse out the general type, loaded and total values
      36                 :         92 :         let type = event.type = event.str.split('(')[0].split('.').pop();
      37                 :         92 :         let loadedAndTotal = event.str.match(/.*\((\d+),(\d+),(true|false)\)/);
      38                 :         92 : 
      39       [ + ][ + ]:         92 :         if(loadedAndTotal){
      40                 :         62 :                 event.loaded = parseInt(loadedAndTotal[1]);
      41                 :         62 :                 event.total  = parseInt(loadedAndTotal[2]);
      42                 :         62 :                 event.lengthComputable = loadedAndTotal[3] == 'true';
      43                 :         62 :         }
      44                 :         92 : 
      45                 :         92 :         return event;
      46                 :         92 : }
      47                 :         17 : 
      48       [ + ][ + ]:         17 : export function prepare_xhr_for_event_order_test(xhr){
      49                 :          6 : 
      50       [ + ][ + ]:          6 :         xhr.addEventListener('readystatechange', () => {
      51                 :         15 :                 recorded_xhr_events.push(xhr.readyState);
      52                 :         15 :                 actual_xhr_events.push(xhr.readyState);
      53                 :          6 :         });
      54                 :          6 : 
      55                 :          6 :         const events = ['loadstart', 'progress', 'abort', 'timeout', 'error', 'load', 'loadend'];
      56                 :          6 : 
      57       [ + ][ + ]:          6 :         for(let i = 0; i < events.length; ++i){
      58                 :         42 :                 xhr.addEventListener(events[i], record_xhr_event);
      59                 :         42 :         }
      60                 :          6 : 
      61                 :          6 :         if('upload' in xhr){
      62       [ + ][ + ]:          6 :                 for(let i = 0; i < events.length; ++i){
      63                 :         42 :                         xhr.upload.addEventListener(events[i], record_xhr_event);
      64                 :         42 :                 }
      65                 :          6 :         }
      66                 :          6 : }
      67                 :         17 : 
      68       [ + ][ + ]:         17 : export function assert_xhr_event_order_matches(expected){
      69                 :          6 :         let recorded = recorded_xhr_events;
      70                 :          6 :         let lastRecordedLoaded = -1;
      71                 :          6 : 
      72  [ + ][ + ][ + ]:          6 :         while(expected.length && recorded.length){
                    [ + ]
      73                 :         46 :                 let currentExpected  = getNextEvent(expected);
      74                 :         46 :                 let currentRecorded  = getNextEvent(recorded);
      75                 :         46 : 
      76                 :         46 :                 // skip to the last progress event if we've hit one (note the next
      77                 :         46 :                 // event after a progress event should be a LOADING readystatechange,
      78                 :         46 :                 // if there are multiple progress events in a row).
      79                 :         46 : 
      80  [ + ][ + ][ + ]:         46 :                 while(recorded.length && currentRecorded.type == `progress` && parseInt(recorded) === 3){
               [ + ][ - ]
      81                 :          0 : 
      82                 :          0 :                         assert(typeof currentRecorded.loaded === 'number');
      83                 :          0 :                         assert(currentRecorded.loaded > lastRecordedLoaded, `progress event 'loaded' values must only increase`);
      84                 :          0 : 
      85                 :          0 :                         lastRecordedLoaded = currentRecorded.loaded;
      86                 :          0 :                 }
      87                 :         46 : 
      88       [ + ][ + ]:         46 :                 if(currentRecorded.type == 'loadend'){
      89                 :         10 :                         let recordedProgressCount = 0;
      90                 :         10 :                         lastRecordedLoaded = -1;
      91                 :         10 :                 }
      92                 :         46 : 
      93                 :         46 :                 assert(currentRecorded.str === currentExpected.str, `currentRecorded.str: ${currentRecorded.str} !== currentExpected.str: ${currentExpected.str}`);
      94                 :         46 :         }
      95                 :          6 : 
      96       [ - ][ - ]:          6 :         if(recorded.length){
      97                 :          0 :                 throw '\nUnexpected extra events: ' + recorded.join(', ');
      98                 :          0 :         }
      99                 :          6 : 
     100       [ - ][ - ]:          6 :         if(expected.length){
     101                 :          0 :                 throw '\nExpected more events: ' + expected.join(', ');
     102                 :          0 :         }
     103                 :          6 : }
     104                 :         17 : 
     105                 :         17 : export function show_xhr_events(){
     106                 :          0 :         return actual_xhr_events;
     107                 :          0 : }
     108                 :         17 : 
     109                 :         17 : /*
     110                 :         17 :  * xmlhttprequest-event-order.js
     111                 :         17 :  *
     112                 :         17 : 
     113                 :         17 : (function(global) {
     114                 :         17 :   var recorded_xhr_events = [];
     115                 :         17 : 
     116                 :         17 :   function record_xhr_event(e) {
     117                 :         17 :     var prefix = e.target instanceof XMLHttpRequestUpload ? "upload." : "";
     118                 :         17 :     recorded_xhr_events.push((prefix || "") + e.type + "(" + e.loaded + "," + e.total + "," + e.lengthComputable + ")");
     119                 :         17 :   }
     120                 :         17 : 
     121                 :         17 :   global.prepare_xhr_for_event_order_test = function(xhr) {
     122                 :         17 :     xhr.addEventListener("readystatechange", function(e) {
     123                 :         17 :       recorded_xhr_events.push(xhr.readyState);
     124                 :         17 :     });
     125                 :         17 :     var events = ["loadstart", "progress", "abort", "timeout", "error", "load", "loadend"];
     126                 :         17 :     for(var i=0; i<events.length; ++i) {
     127                 :         17 :       xhr.addEventListener(events[i], record_xhr_event);
     128                 :         17 :     }
     129                 :         17 :     if ("upload" in xhr) {
     130                 :         17 :       for(var i=0; i<events.length; ++i) {
     131                 :         17 :         xhr.upload.addEventListener(events[i], record_xhr_event);
     132                 :         17 :       }
     133                 :         17 :     }
     134                 :         17 :   }
     135                 :         17 : 
     136                 :         17 :   function getNextEvent(arr) {
     137                 :         17 :     var event = { str: arr.shift() };
     138                 :         17 : 
     139                 :         17 :     // we can only handle strings, numbers (readystates) and undefined
     140                 :         17 :     if (event.str === undefined) {
     141                 :         17 :       return event;
     142                 :         17 :     }
     143                 :         17 : 
     144                 :         17 :     if (typeof event.str !== "string") {
     145                 :         17 :       if (Number.isInteger(event.str)) {
     146                 :         17 :         event.state = event.str;
     147                 :         17 :         event.str = "readystatechange(" + event.str + ")";
     148                 :         17 :       } else {
     149                 :         17 :         throw "Test error: unexpected event type " + event.str;
     150                 :         17 :       }
     151                 :         17 :     }
     152                 :         17 : 
     153                 :         17 :     // parse out the general type, loaded and total values
     154                 :         17 :     var type = event.type = event.str.split("(")[0].split(".").pop();
     155                 :         17 :     var loadedAndTotal = event.str.match(/.*\((\d+),(\d+),(true|false)\)/);
     156                 :         17 :     if (loadedAndTotal) {
     157                 :         17 :       event.loaded = parseInt(loadedAndTotal[1]);
     158                 :         17 :       event.total = parseInt(loadedAndTotal[2]);
     159                 :         17 :       event.lengthComputable = loadedAndTotal[3] == "true";
     160                 :         17 :     }
     161                 :         17 : 
     162                 :         17 :     return event;
     163                 :         17 :   }
     164                 :         17 : 
     165                 :         17 :   global.assert_xhr_event_order_matches = function(expected) {
     166                 :         17 :     var recorded = recorded_xhr_events;
     167                 :         17 :     var lastRecordedLoaded = -1;
     168                 :         17 :     while(expected.length && recorded.length) {
     169                 :         17 :       var currentExpected = getNextEvent(expected),
     170                 :         17 :           currentRecorded = getNextEvent(recorded);
     171                 :         17 : 
     172                 :         17 :       // skip to the last progress event if we've hit one (note the next
     173                 :         17 :       // event after a progress event should be a LOADING readystatechange,
     174                 :         17 :       // if there are multiple progress events in a row).
     175                 :         17 :       while (recorded.length && currentRecorded.type == "progress" &&
     176                 :         17 :              parseInt(recorded) === 3) {
     177                 :         17 :         assert_greater_than(currentRecorded.loaded, lastRecordedLoaded,
     178                 :         17 :                             "progress event 'loaded' values must only increase");
     179                 :         17 :         lastRecordedLoaded = currentRecorded.loaded;
     180                 :         17 :       }
     181                 :         17 :       if (currentRecorded.type == "loadend") {
     182                 :         17 :         recordedProgressCount = 0;
     183                 :         17 :         lastRecordedLoaded = -1;
     184                 :         17 :       }
     185                 :         17 : 
     186                 :         17 :       assert_equals(currentRecorded.str, currentExpected.str);
     187                 :         17 :     }
     188                 :         17 :     if (recorded.length) {
     189                 :         17 :       throw "\nUnexpected extra events: " + recorded.join(", ");
     190                 :         17 :     }
     191                 :         17 :     if (expected.length) {
     192                 :         17 :       throw "\nExpected more events: " + expected.join(", ");
     193                 :         17 :     }
     194                 :         17 :   }
     195                 :         17 : }(this));
     196                 :         17 : 
     197                 :         17 :  *
     198                 :         17 :  * xmlhttprequest-event-order.js
     199                 :         17 :  */

Generated by: LCOV version 1.14