|
1 | 1 | // ==UserScript== |
2 | 2 | // @name GM_xmlhttpRequest Exhaustive Test Harness v3 |
3 | 3 | // @namespace tm-gmxhr-test |
4 | | -// @version 1.2.4 |
| 4 | +// @version 1.2.5 |
5 | 5 | // @description Comprehensive in-page tests for GM_xmlhttpRequest: normal, abnormal, and edge cases with clear pass/fail output. |
6 | 6 | // @author you |
7 | 7 | // @match *://*/*?GM_XHR_TEST_SC |
@@ -120,8 +120,7 @@ const enableTool = true; |
120 | 120 | gap: "8px", |
121 | 121 | }, |
122 | 122 | }, |
123 | | - h("div", { style: { fontWeight: "600" } }, "GM_xmlhttpRequest Test Harness", h("br"), `${GM.info?.version}`), |
124 | | - h("div", { id: "counts", style: { marginLeft: "auto", opacity: 0.8 } }, "…"), |
| 123 | + h("div", {}, h("div", { style: { fontWeight: "500" } }, `GM_xmlhttpRequest Test Harness ${GM.info?.script?.version}`), h("div", { style: { display: "flex", flexDirection: "row" } }, h("div", { style: { fontWeight: "400" } }, `${GM.info?.scriptHandler} ${GM.info?.version}`), h("div", { id: "counts", style: { marginLeft: "auto", opacity: 0.8 } }, "…"))), |
125 | 124 | h("button", { id: "start", style: btn() }, "Run"), |
126 | 125 | h("button", { id: "clear", style: btn() }, "Clear") |
127 | 126 | ), |
@@ -938,6 +937,82 @@ const enableTool = true; |
938 | 937 | } |
939 | 938 | }, |
940 | 939 | }, |
| 940 | + { |
| 941 | + name: "GM_xhr abort timeout onloadend events", |
| 942 | + async run(fetch) { |
| 943 | + const runCase = (details, { abortAfterMs } = {}) => { |
| 944 | + return new Promise((resolve, reject) => { |
| 945 | + const events = []; |
| 946 | + const timeoutMs = Math.max((details.timeout || 0) + (abortAfterMs || 0) + 8000, 12000); |
| 947 | + const timer = setTimeout(() => { |
| 948 | + reject(new Error(`Expected onloadend; events=${events.join(",")}`)); |
| 949 | + }, timeoutMs); |
| 950 | + const req = GM_xmlhttpRequest({ |
| 951 | + method: details.method || "GET", |
| 952 | + url: details.url, |
| 953 | + timeout: details.timeout, |
| 954 | + fetch, |
| 955 | + onload() { |
| 956 | + events.push("onload"); |
| 957 | + }, |
| 958 | + onerror() { |
| 959 | + events.push("onerror"); |
| 960 | + }, |
| 961 | + onabort() { |
| 962 | + events.push("onabort"); |
| 963 | + }, |
| 964 | + ontimeout() { |
| 965 | + events.push("ontimeout"); |
| 966 | + }, |
| 967 | + onloadend(response) { |
| 968 | + events.push("onloadend"); |
| 969 | + clearTimeout(timer); |
| 970 | + resolve({ events, response }); |
| 971 | + }, |
| 972 | + }); |
| 973 | + if (abortAfterMs != null) { |
| 974 | + setTimeout(() => req.abort(), abortAfterMs); |
| 975 | + } |
| 976 | + }); |
| 977 | + }; |
| 978 | + |
| 979 | + const normal = await runCase({ |
| 980 | + url: `${HB}/get`, |
| 981 | + }); |
| 982 | + assertDeepEq(normal.events, ["onload", "onloadend"], "normal fires onload then onloadend"); |
| 983 | + assertEq(normal.response.status, 200, "normal onloadend status 200"); |
| 984 | + |
| 985 | + const timeout = await runCase({ |
| 986 | + url: `${HB}/delay/5`, |
| 987 | + timeout: 2000, |
| 988 | + }); |
| 989 | + assertDeepEq(timeout.events, ["ontimeout", "onloadend"], "timeout fires ontimeout then onloadend"); |
| 990 | + |
| 991 | + const abort = await runCase( |
| 992 | + { |
| 993 | + url: `${HB}/delay/10`, |
| 994 | + }, |
| 995 | + { abortAfterMs: 4000 } |
| 996 | + ); |
| 997 | + assertDeepEq(abort.events, ["onabort", "onloadend"], "abort fires onabort then onloadend"); |
| 998 | + |
| 999 | + const nwError1 = await runCase( |
| 1000 | + { |
| 1001 | + url: `https://nonexistent-domain-abcxyz.test/abc.html`, // allowed domain |
| 1002 | + }, |
| 1003 | + { abortAfterMs: 500 } |
| 1004 | + ); |
| 1005 | + assertDeepEq(nwError1.events, ["onerror", "onloadend"], "abort fires onerror then onloadend"); |
| 1006 | + |
| 1007 | + const nwError2 = await runCase( |
| 1008 | + { |
| 1009 | + url: `https://nonexistent-domain-abcxyz.reject/abc.html`, // disallowed domain |
| 1010 | + }, |
| 1011 | + { abortAfterMs: 500 } |
| 1012 | + ); |
| 1013 | + assertDeepEq(nwError2.events, ["onerror", "onloadend"], "abort fires onerror then onloadend"); |
| 1014 | + }, |
| 1015 | + }, |
941 | 1016 | { |
942 | 1017 | name: "onprogress fires while downloading [arraybuffer]", |
943 | 1018 | async run(fetch) { |
|
0 commit comments