Skip to content

Commit 798f4ae

Browse files
committed
updating injector spec
1 parent 61cc17a commit 798f4ae

File tree

1 file changed

+9
-185
lines changed

1 file changed

+9
-185
lines changed

packages/proxy/test/unit/http/util/service-worker-injector.spec.ts

+9-185
Original file line numberDiff line numberDiff line change
@@ -6,194 +6,18 @@ describe('lib/http/util/service-worker-injector', () => {
66
it('injects into the service worker', () => {
77
const actual = injectIntoServiceWorker(Buffer.from('foo'))
88

9-
const expected = `
9+
// this regex is used to verify the actual output,
10+
// it verifies the service worker has the injected __cypressInjectIntoServiceWorker
11+
// function followed by the contents of the user's service worker (in this case 'foo'),
12+
// it does not verify the contents of __cypressInjectIntoServiceWorker function
13+
// as it is subject to change and is not relevant to the test
14+
const expected = new RegExp(`
1015
let __cypressIsScriptEvaluated = false;
11-
(function __cypressInjectIntoServiceWorker() {
12-
let listenerCount = 0;
13-
let eventQueue = [];
14-
const nonCaptureListenersMap = new WeakMap();
15-
const captureListenersMap = new WeakMap();
16-
const targetToWrappedHandleEventMap = new WeakMap();
17-
const targetToOrigHandleEventMap = new WeakMap();
18-
const sendEvent = (event) => {
19-
// if the binding has been created, we can call it
20-
// otherwise, we need to queue the event
21-
if (self.__cypressServiceWorkerClientEvent) {
22-
self.__cypressServiceWorkerClientEvent(JSON.stringify(event));
23-
}
24-
else {
25-
eventQueue.push(event);
26-
}
27-
};
28-
const sendHasFetchEventHandlers = () => {
29-
// @ts-expect-error __cypressIsScriptEvaluated is declared below
30-
// if the script has been evaluated, we can call the CDP binding to inform the backend whether or not the service worker has a handler
31-
if (__cypressIsScriptEvaluated) {
32-
sendEvent({ type: 'hasFetchHandler', payload: { hasFetchHandler: !!(listenerCount > 0 || self.onfetch) } });
33-
}
34-
};
35-
const sendFetchRequest = (payload) => {
36-
// call the CDP binding to inform the backend whether or not the service worker handled the request
37-
sendEvent({ type: 'fetchRequest', payload });
38-
};
39-
// A listener is considered valid if it is a function or an object (with the handleEvent function or the function could be added later)
40-
const isValidListener = (listener) => {
41-
return listener && (typeof listener === 'function' || typeof listener === 'object');
42-
};
43-
// Determine if the event listener was aborted
44-
const isAborted = (options) => {
45-
var _a;
46-
return typeof options === 'object' && ((_a = options.signal) === null || _a === void 0 ? void 0 : _a.aborted);
47-
};
48-
// Get the capture value from the options
49-
const getCaptureValue = (options) => {
50-
return typeof options === 'boolean' ? options : options === null || options === void 0 ? void 0 : options.capture;
51-
};
52-
function wrapListener(listener) {
53-
return (event) => {
54-
// we want to override the respondWith method so we can track if it was called
55-
// to determine if the service worker handled the request
56-
const oldRespondWith = event.respondWith;
57-
let respondWithCalled = false;
58-
event.respondWith = (...args) => {
59-
respondWithCalled = true;
60-
oldRespondWith.call(event, ...args);
61-
};
62-
let returnValue;
63-
try {
64-
// call the original listener
65-
returnValue = listener.call(self, event);
66-
}
67-
catch (_a) {
68-
// if the listener throws an error, we still want to proceed with calling the binding
69-
}
70-
if (returnValue instanceof Promise) {
71-
// if the listener returns a promise, we need to wait for it to resolve
72-
// before we can determine if the service worker handled the request
73-
returnValue.then(() => {
74-
sendFetchRequest({ url: event.request.url, isControlled: respondWithCalled });
75-
});
76-
}
77-
else {
78-
sendFetchRequest({ url: event.request.url, isControlled: respondWithCalled });
79-
}
80-
return returnValue;
81-
};
82-
}
83-
const oldAddEventListener = self.addEventListener;
84-
// Overwrite the addEventListener method so we can determine if the service worker handled the request
85-
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
86-
self.addEventListener = (type, listener, options) => {
87-
if (type === 'fetch' && isValidListener(listener) && !isAborted(options)) {
88-
const capture = getCaptureValue(options);
89-
const existingListener = capture ? captureListenersMap.get(listener) : nonCaptureListenersMap.get(listener);
90-
// If the listener is already in the map, we don't need to wrap it again
91-
if (existingListener) {
92-
return oldAddEventListener(type, existingListener, options);
93-
}
94-
let newListener;
95-
// If the listener is a function, we can just wrap it
96-
// Otherwise, we need to wrap the listener in a proxy so we can track and wrap the handleEvent function
97-
if (typeof listener === 'function') {
98-
newListener = wrapListener(listener);
99-
}
100-
else {
101-
// since the handleEvent function could change, we need to use a proxy to wrap it
102-
newListener = new Proxy(listener, {
103-
get(target, key) {
104-
if (key === 'handleEvent') {
105-
const wrappedHandleEvent = targetToWrappedHandleEventMap.get(target);
106-
const origHandleEvent = targetToOrigHandleEventMap.get(target);
107-
// If the handleEvent function has not been wrapped yet, or if it has changed, we need to wrap it
108-
if ((!wrappedHandleEvent && target.handleEvent) || target.handleEvent !== origHandleEvent) {
109-
targetToWrappedHandleEventMap.set(target, wrapListener(target.handleEvent));
110-
targetToOrigHandleEventMap.set(target, target.handleEvent);
111-
}
112-
return targetToWrappedHandleEventMap.get(target);
113-
}
114-
return Reflect.get(target, key);
115-
},
116-
});
117-
}
118-
// call the original addEventListener function prior to doing any additional work since it may fail
119-
const result = oldAddEventListener(type, newListener, options);
120-
// get the capture value so we know which map to add the listener to
121-
// so we can then remove the listener later if requested
122-
getCaptureValue(options) ? captureListenersMap.set(listener, newListener) : nonCaptureListenersMap.set(listener, newListener);
123-
listenerCount++;
124-
sendHasFetchEventHandlers();
125-
return result;
126-
}
127-
return oldAddEventListener(type, listener, options);
128-
};
129-
const oldRemoveEventListener = self.removeEventListener;
130-
// Overwrite the removeEventListener method so we can remove the listener from the map
131-
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener
132-
self.removeEventListener = (type, listener, options) => {
133-
if (type === 'fetch' && isValidListener(listener)) {
134-
// get the capture value so we know which map to remove the listener from
135-
const capture = getCaptureValue(options);
136-
const newListener = capture ? captureListenersMap.get(listener) : nonCaptureListenersMap.get(listener);
137-
// call the original removeEventListener function prior to doing any additional work since it may fail
138-
const result = oldRemoveEventListener(type, newListener, options);
139-
capture ? captureListenersMap.delete(listener) : nonCaptureListenersMap.delete(listener);
140-
listenerCount--;
141-
// If the listener is an object with a handleEvent method, we need to remove the wrapped function
142-
if (typeof listener === 'object' && typeof listener.handleEvent === 'function') {
143-
targetToWrappedHandleEventMap.delete(listener);
144-
targetToOrigHandleEventMap.delete(listener);
145-
}
146-
sendHasFetchEventHandlers();
147-
return result;
148-
}
149-
return oldRemoveEventListener(type, listener, options);
150-
};
151-
const originalPropertyDescriptor = Object.getOwnPropertyDescriptor(self, 'onfetch');
152-
if (!originalPropertyDescriptor) {
153-
return;
154-
}
155-
// Overwrite the onfetch property so we can
156-
// determine if the service worker handled the request
157-
Object.defineProperty(self, 'onfetch', {
158-
configurable: originalPropertyDescriptor.configurable,
159-
enumerable: originalPropertyDescriptor.enumerable,
160-
get() {
161-
var _a;
162-
return (_a = originalPropertyDescriptor.get) === null || _a === void 0 ? void 0 : _a.call(this);
163-
},
164-
set(value) {
165-
var _a;
166-
let newHandler;
167-
if (value) {
168-
newHandler = wrapListener(value);
169-
}
170-
(_a = originalPropertyDescriptor.set) === null || _a === void 0 ? void 0 : _a.call(this, newHandler);
171-
sendHasFetchEventHandlers();
172-
},
173-
});
174-
// listen for the activate event so we can inform the
175-
// backend whether or not the service worker has a handler
176-
self.addEventListener('activate', () => {
177-
sendHasFetchEventHandlers();
178-
// if the binding has not been created yet, we need to wait for it
179-
if (!self.__cypressServiceWorkerClientEvent) {
180-
const timer = setInterval(() => {
181-
if (self.__cypressServiceWorkerClientEvent) {
182-
clearInterval(timer);
183-
// send any events that were queued
184-
eventQueue.forEach((event) => {
185-
self.__cypressServiceWorkerClientEvent(JSON.stringify(event));
186-
});
187-
eventQueue = [];
188-
}
189-
}, 5);
190-
}
191-
});
192-
})();
16+
\\(function __cypressInjectIntoServiceWorker\\(\\) \\{.*\\}\\)\\(\\);
19317
foo;
194-
__cypressIsScriptEvaluated = true;`
18+
__cypressIsScriptEvaluated = true;`.replace(/\s/g, ''))
19519

196-
expect(actual.replace(/\s/g, '')).to.equal(expected.replace(/\s/g, ''))
20+
expect(actual.replace(/\s/g, '')).to.match(expected)
19721
})
19822
})
19923
})

0 commit comments

Comments
 (0)