Skip to content

improve waitForFetch proxy #518

@Techn1x

Description

@Techn1x

Hello!

TLDR; I think we need to update the waitForFetch() function to proxy more of the Response. After updating from pretender -> MSW I noticed a few issues, likely due to MSW using a different Response to what pretender provides


After switching to MSW, I noticed that waitForFetch's Response Proxy started throwing errors on some of the calls made against the Response. Specifically, the Reflect.get() call would throw "Illegal invocation" error, when ok, status, statusText etc were asked for - any properties of Response. Functions calls like json etc remained fine.

return new Proxy(response, {
get(target, prop, receiver) {
const original = Reflect.get(target, prop, receiver);
if (
typeof prop === 'string' &&
['json', 'text', 'arrayBuffer', 'blob', 'formData', 'bytes'].includes(prop)
) {
return (...args: unknown[]) => {
return waitForPromise(original.call(target, ...args));
};

Some research into the error suggests that this is something to do with the receiver arg there to Reflect.get(). To fix this, we just make sure to avoid it for property calls like ok etc.

Additionally, for function calls like clone() that aren't async, we need to call them (but no need to wrap in waitForPromise for those).

My patch looks like this currently, and it's working great. I'll probably turn this into a PR

   const response = await waitForPromise(fetchPromise);
   return new Proxy(response, {
     get(target, prop, receiver) {
+      if (
+        typeof prop === 'string' &&
+        ['ok', 'status', 'statusText', 'bodyUsed', 'headers', 'redirected', 'type', 'url'].includes(prop)
+      ) {
+        return target[prop];
+      }
       const original = Reflect.get(target, prop, receiver);
       if (typeof prop === 'string' && ['json', 'text', 'arrayBuffer', 'blob', 'formData', 'bytes'].includes(prop)) {
         return (...args) => {
           return waitForPromise(original.call(target, ...args));
         };
       }
+      if (typeof prop === 'string' && ['clone'].includes(prop)) {
+        return (...args) => {
+          return original.call(target, ...args);
+        }
+      }
       return original;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions