Repository: wheresrhys/fetch-mock
Pull request #675 (2024-06-15 19:25:57)

accept data: URLs


Patch:
diff --git a/src/lib/request-utils.js b/src/lib/request-utils.js
index 1c32669..2726d8c 100644
--- a/src/lib/request-utils.js
+++ b/src/lib/request-utils.js
@@ -1,6 +1,6 @@
-// https://stackoverflow.com/a/19709846/308237
-// split, URL constructor does not support protocol-relative urls
-const absoluteUrlRX = new RegExp('^[a-z]+://', 'i');
+// https://stackoverflow.com/a/19709846/308237 plus data: scheme
+// split into 2 code paths as URL constructor does not support protocol-relative urls
+const absoluteUrlRX = new RegExp('^[a-z]+://|^data:', 'i');
 const protocolRelativeUrlRX = new RegExp('^//', 'i');
 
 const headersToArray = (headers) => {


Test patch:
diff --git a/test/specs/routing/url-matching.test.js b/test/specs/routing/url-matching.test.js
index ce52cf8..91e9600 100644
--- a/test/specs/routing/url-matching.test.js
+++ b/test/specs/routing/url-matching.test.js
@@ -135,4 +135,69 @@ describe('url matching', () => {
 			expect(fm.calls(true).length).toEqual(1);
 		});
 	});
+
+	describe('data: URLs', () => {
+		it('match exact strings', async () => {
+			fm.mock('data:text/plain,path', 200).catch();
+			await fm.fetchHandler('data:text/plain,pat');
+			await fm.fetchHandler('data:text/plain,paths');
+			await fm.fetchHandler('data:text/html,path');
+			expect(fm.calls(true).length).to.equal(0);
+			await fm.fetchHandler('data:text/plain,path');
+			expect(fm.calls(true).length).to.equal(1);
+		});
+		it('match exact string against URL object', async () => {
+			fm.mock('data:text/plain,path', 200).catch();
+			const url = new URL('data:text/plain,path');
+			await fm.fetchHandler(url);
+			expect(fm.calls(true).length).to.equal(1);
+		});
+		it('match using URL object as matcher', async () => {
+			const url = new URL('data:text/plain,path');
+			fm.mock(url, 200).catch();
+			await fm.fetchHandler('data:text/plain,path');
+			expect(fm.calls(true).length).to.equal(1);
+		});
+		it('match begin: keyword', async () => {
+			fm.mock('begin:data:text/plain', 200).catch();
+			await fm.fetchHandler('http://a.com/path');
+			await fm.fetchHandler('data:text/html,path');
+			expect(fm.calls(true).length).to.equal(0);
+			await fm.fetchHandler('data:text/plain,path');
+			await fm.fetchHandler('data:text/plain;base64,cGF0aA');
+			expect(fm.calls(true).length).to.equal(2);
+		});
+		it('match end: keyword', async () => {
+			fm.mock('end:sky', 200).catch();
+			await fm.fetchHandler('data:text/plain,blue lake');
+			await fm.fetchHandler('data:text/plain,blue sky research');
+			expect(fm.calls(true).length).to.equal(0);
+			await fm.fetchHandler('data:text/plain,blue sky');
+			await fm.fetchHandler('data:text/plain,grey sky');
+			expect(fm.calls(true).length).to.equal(2);
+		});
+		it('match glob: keyword', async () => {
+			fm.mock('glob:data:* sky', 200).catch();
+			await fm.fetchHandler('data:text/plain,blue lake');
+			expect(fm.calls(true).length).to.equal(0);
+			await fm.fetchHandler('data:text/plain,blue sky');
+			await fm.fetchHandler('data:text/plain,grey sky');
+			expect(fm.calls(true).length).to.equal(2);
+		});
+		it('match wildcard string', async () => {
+			fm.mock('*', 200);
+			await fm.fetchHandler('data:text/plain,path');
+			expect(fm.calls(true).length).to.equal(1);
+		});
+		it('match regular expressions', async () => {
+			const rx = /data\:text\/plain,\d+/;
+			fm.mock(rx, 200).catch();
+			await fm.fetchHandler('data:text/html,12345');
+			expect(fm.calls(true).length).to.equal(0);
+			await fm.fetchHandler('data:text/plain,12345');
+			expect(fm.calls(true).length).to.equal(1);
+			await fm.fetchHandler('data:text/plain,path');
+			expect(fm.calls(true).length).to.equal(1);
+		});
+	});
 });