Skip to content

Commit

Permalink
add replacement logic
Browse files Browse the repository at this point in the history
  • Loading branch information
stanislav-atr committed Oct 31, 2022
1 parent edafb05 commit 522ade9
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 115 deletions.
108 changes: 52 additions & 56 deletions src/scriptlets/trusted-replace-fetch-response.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,11 @@ export function trustedReplaceFetchResponse(source, pattern = '', replacement =
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
if (typeof fetch === 'undefined'
|| typeof Proxy === 'undefined'
|| typeof Response === 'undefined') {
|| typeof Response === 'undefined'
|| typeof Promise === 'undefined') {
return;
}
debugger;

const shouldLog = typeof pattern === 'undefined';

if (!shouldLog && (pattern === '' || typeof replacement === 'undefined')) {
Expand Down Expand Up @@ -117,61 +118,56 @@ export function trustedReplaceFetchResponse(source, pattern = '', replacement =
return Reflect.apply(target, thisArg, args);
}

// Send original request to retrieve response data
let response;
try {
response = await nativeFetch(...args);
} catch {
return Reflect.apply(target, thisArg, args);
}

// Try to convert response body to text
let bodyText;
try {
bodyText = await response.text();
} catch {
// log if response body can't be converted to a string
const fetchDataStr = objectToString(fetchData);
const logMessage = `log: Response body can't be converted to text: ${fetchDataStr}`;
log(source, logMessage);
return Reflect.apply(target, thisArg, args);
}
const forgeResponse = (response, text) => {
const {
bodyUsed,
headers,
ok,
redirected,
status,
statusText,
type,
url,
} = response;

const patternRegexp = pattern === getWildcardSymbol()
? toRegExp
: toRegExp(pattern);

const modifiedContent = text.replace(patternRegexp, replacement);

// eslint-disable-next-line compat/compat
const fiddledResponse = new Response(modifiedContent, {
status,
statusText,
headers,
});

// Manually set properties which can't be set by Response constructor
Object.defineProperties(fiddledResponse, {
url: { value: url },
type: { value: type },
ok: { value: ok },
bodyUsed: { value: bodyUsed },
redirected: { value: redirected },
});

const {
bodyUsed,
headers,
ok,
redirected,
status,
statusText,
type,
url,
} = response;

const patternRegexp = pattern === getWildcardSymbol()
? toRegExp
: toRegExp(pattern);

const modifiedContent = bodyText.replace(patternRegexp, replacement);

// eslint-disable-next-line compat/compat
const fiddledResponse = new Response(modifiedContent, {
status,
statusText,
headers,
});

// Manually set properties which can't be set by Response constructor
Object.defineProperties(fiddledResponse, {
url: { value: url },
type: { value: type },
ok: { value: ok },
bodyUsed: { value: bodyUsed },
redirected: { value: redirected },
});

hit(source);
return fiddledResponse;
hit(source);
};

return nativeFetch(...args)
.then((response) => {
return response.text()
.then((bodyText) => forgeResponse(response, bodyText))
.catch(() => {
// log if response body can't be converted to a string
const fetchDataStr = objectToString(fetchData);
const logMessage = `log: Response body can't be converted to text: ${fetchDataStr}`;
log(source, logMessage);
return Reflect.apply(target, thisArg, args);
});
})
.catch(() => Reflect.apply(target, thisArg, args));
};

const fetchHandler = {
Expand Down
92 changes: 33 additions & 59 deletions tests/scriptlets/trusted-replace-fetch-response.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,63 +33,37 @@ if (!isSupported) {
assert.ok(true, 'Browser does not support it');
});
} else {
// test('No arguments, logging', async (assert) => {
// const INPUT_JSON_PATH = `${FETCH_OBJECTS_PATH}/test01.json`;
// const TEST_METHOD = 'POST';
// const init = {
// method: TEST_METHOD,
// };
// const expectedJson = {
// a1: 1,
// b2: 'test',
// c3: 3,
// };
// const done = assert.async();

// // mock console.log function for log checking
// console.log = function log(input) {
// if (input.indexOf('trace') > -1) {
// return;
// }
// // eslint-disable-next-line max-len
// const EXPECTED_LOG_STR_START = `fetch( url:"${INPUT_JSON_PATH}" method:"${TEST_METHOD}"`;
// assert.ok(startsWith(input, EXPECTED_LOG_STR_START), 'console.hit input');
// };

// // no args -> just logging, no preventing
// runScriptlet(name);

// const response = await fetch(INPUT_JSON_PATH, init);
// const actualJson = await response.json();

// assert.strictEqual(window.hit, 'FIRED', 'hit function fired');
// assert.deepEqual(actualJson, expectedJson);
// done();
// });

// test('Pattern(string) & replacement, match all requests', async (assert) => {
// const INPUT_JSON_PATH_1 = `${FETCH_OBJECTS_PATH}/test01.json`;
// const inputRequest1 = new Request(INPUT_JSON_PATH_1);

// const INPUT_JSON_PATH_2 = `${FETCH_OBJECTS_PATH}/test02.json`;
// const init2 = {
// method: 'GET',
// };

// const PATTERN = 'test';
// const REPLACEMENT = 'REPLACEMENT';

// runScriptlet(name, [PATTERN, REPLACEMENT, '*']);
// const done1 = assert.async();
// // const done2 = assert.async();

// const response1 = await fetch(inputRequest1);
// const parsedData1 = await response1.text();

// assert.notOk(parsedData1.includes(PATTERN), 'Pattern is removed');
// assert.ok(parsedData1.includes(REPLACEMENT), 'Replacement is set');
// assert.strictEqual(window.hit, 'FIRED', 'hit function fired');
// done1();
// clearGlobalProps('hit');
// });
test('No arguments, logging', async (assert) => {
const INPUT_JSON_PATH = `${FETCH_OBJECTS_PATH}/test01.json`;
const TEST_METHOD = 'POST';
const init = {
method: TEST_METHOD,
};
const expectedJson = {
a1: 1,
b2: 'test',
c3: 3,
};
const done = assert.async();

// mock console.log function for log checking
console.log = function log(input) {
if (input.indexOf('trace') > -1) {
return;
}
// eslint-disable-next-line max-len
const EXPECTED_LOG_STR_START = `fetch( url:"${INPUT_JSON_PATH}" method:"${TEST_METHOD}"`;
assert.ok(startsWith(input, EXPECTED_LOG_STR_START), 'console.hit input');
};

// no args -> just logging, no replacements
runScriptlet(name);

const response = await fetch(INPUT_JSON_PATH, init);
const actualJson = await response.json();

assert.strictEqual(window.hit, 'FIRED', 'hit function fired');
assert.deepEqual(actualJson, expectedJson);
done();
});
}

0 comments on commit 522ade9

Please sign in to comment.