Skip to content

Commit c21d36f

Browse files
committed
updates
1 parent 5aed7ce commit c21d36f

File tree

4 files changed

+113
-2
lines changed

4 files changed

+113
-2
lines changed

packages/driver/cypress/e2e/e2e/service-worker.cy.js

+101
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,41 @@
11
describe('service workers', () => {
2+
let sessionId
3+
4+
const getSessionId = async () => {
5+
if (!sessionId) {
6+
const targets = (await Cypress.automation('remote:debugger:protocol', { command: 'Target.getTargets', params: {} })).targetInfos
7+
const serviceWorkerTarget = targets.reverse().find((target) => target.type === 'service_worker' && target.url === 'http://localhost:3500/fixtures/service-worker.js')
8+
9+
;({ sessionId } = await Cypress.automation('remote:debugger:protocol', { command: 'Target.attachToTarget', params: { targetId: serviceWorkerTarget.targetId, flatten: true } }))
10+
}
11+
12+
return sessionId
13+
}
14+
15+
const getEventListenersLength = async () => {
16+
const sessionId = await getSessionId()
17+
let result = await Cypress.automation('remote:debugger:protocol', { command: 'Runtime.evaluate', params: { expression: 'getEventListeners(self).fetch', includeCommandLineAPI: true }, sessionId })
18+
19+
if (result.result.type === 'undefined') return 0
20+
21+
result = await Cypress.automation('remote:debugger:protocol', { command: 'Runtime.getProperties', params: { objectId: result.result.objectId }, sessionId })
22+
23+
const length = result.result.find((prop) => prop.name === 'length').value.value
24+
25+
return length
26+
}
27+
28+
const getOnFetchHandlerType = async () => {
29+
const sessionId = await getSessionId()
30+
31+
const result = await Cypress.automation('remote:debugger:protocol', { command: 'Runtime.evaluate', params: { expression: 'self.onfetch', includeCommandLineAPI: true }, sessionId })
32+
33+
return result.result.type
34+
}
35+
236
beforeEach(async () => {
37+
sessionId = null
38+
339
// unregister the service worker to ensure it does not affect other tests
440
const registrations = await navigator.serviceWorker.getRegistrations()
541

@@ -21,6 +57,9 @@ describe('service workers', () => {
2157

2258
cy.visit('fixtures/service-worker.html')
2359
cy.get('#output').should('have.text', 'done')
60+
cy.then(async () => {
61+
expect(await getEventListenersLength()).to.equal(1)
62+
})
2463
})
2564

2665
it('supports using addEventListener with object', () => {
@@ -41,6 +80,9 @@ describe('service workers', () => {
4180

4281
cy.visit('fixtures/service-worker.html')
4382
cy.get('#output').should('have.text', 'done')
83+
cy.then(async () => {
84+
expect(await getEventListenersLength()).to.equal(1)
85+
})
4486
})
4587

4688
it('supports using addEventListener with delayed handleEvent', () => {
@@ -60,6 +102,9 @@ describe('service workers', () => {
60102

61103
cy.visit('fixtures/service-worker.html')
62104
cy.get('#output').should('have.text', 'done')
105+
cy.then(async () => {
106+
expect(await getEventListenersLength()).to.equal(1)
107+
})
63108
})
64109

65110
it('supports using onfetch', () => {
@@ -76,6 +121,11 @@ describe('service workers', () => {
76121

77122
cy.visit('fixtures/service-worker.html')
78123
cy.get('#output').should('have.text', 'done')
124+
cy.then(async () => {
125+
// onfetch will add an event listener
126+
expect(await getEventListenersLength()).to.equal(1)
127+
expect(await getOnFetchHandlerType()).to.equal('function')
128+
})
79129
})
80130
})
81131

@@ -94,6 +144,9 @@ describe('service workers', () => {
94144

95145
cy.visit('fixtures/service-worker.html')
96146
cy.get('#output').should('have.text', 'done')
147+
cy.then(async () => {
148+
expect(await getEventListenersLength()).to.equal(1)
149+
})
97150
})
98151

99152
it('supports using onfetch', () => {
@@ -110,6 +163,11 @@ describe('service workers', () => {
110163

111164
cy.visit('fixtures/service-worker.html')
112165
cy.get('#output').should('have.text', 'done')
166+
cy.then(async () => {
167+
// onfetch will add an event listener
168+
expect(await getEventListenersLength()).to.equal(1)
169+
expect(await getOnFetchHandlerType()).to.equal('function')
170+
})
113171
})
114172
})
115173

@@ -138,6 +196,9 @@ describe('service workers', () => {
138196

139197
cy.visit('fixtures/service-worker.html')
140198
cy.get('#output').should('have.text', 'done')
199+
cy.then(async () => {
200+
expect(await getEventListenersLength()).to.equal(1)
201+
})
141202
})
142203

143204
it('supports using onfetch', () => {
@@ -163,6 +224,11 @@ describe('service workers', () => {
163224

164225
cy.visit('fixtures/service-worker.html')
165226
cy.get('#output').should('have.text', 'done')
227+
cy.then(async () => {
228+
// onfetch will add an event listener
229+
expect(await getEventListenersLength()).to.equal(1)
230+
expect(await getOnFetchHandlerType()).to.equal('function')
231+
})
166232
})
167233
})
168234

@@ -185,6 +251,41 @@ describe('service workers', () => {
185251

186252
cy.visit('fixtures/service-worker.html')
187253
cy.get('#output').should('have.text', 'done')
254+
cy.then(async () => {
255+
// onfetch will also add an event listener
256+
expect(await getEventListenersLength()).to.equal(2)
257+
expect(await getOnFetchHandlerType()).to.equal('function')
258+
})
259+
})
260+
261+
it('supports other options', () => {
262+
const script = () => {
263+
const handler = function (event) {
264+
event.respondWith(fetch(event.request))
265+
}
266+
267+
self.addEventListener('fetch', handler)
268+
269+
// this one does not get added because capture is the same
270+
self.addEventListener('fetch', handler, { capture: false })
271+
272+
// this one gets added because capture is different
273+
self.addEventListener('fetch', handler, { capture: true })
274+
275+
// this one does not get added because capture is the same
276+
self.addEventListener('fetch', handler, { once: true })
277+
}
278+
279+
cy.intercept('/fixtures/service-worker.js', (req) => {
280+
req.reply(`(${script})()`,
281+
{ 'Content-Type': 'application/javascript' })
282+
})
283+
284+
cy.visit('fixtures/service-worker.html')
285+
cy.get('#output').should('have.text', 'done')
286+
cy.then(async () => {
287+
expect(await getEventListenersLength()).to.equal(2)
288+
})
188289
})
189290
})
190291
})

packages/proxy/lib/http/util/service-worker-rewriter.ts

+9
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export const rewriteServiceWorker = (body: Buffer) => {
1818
oldRespondWith.call(event, ...args)
1919
}
2020

21+
// call the original listener
2122
const returnValue = listener(event)
2223

2324
// @ts-expect-error
@@ -49,6 +50,14 @@ export const rewriteServiceWorker = (body: Buffer) => {
4950
// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
5051
self.addEventListener = (type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions) => {
5152
if (type === 'fetch' && isValidListener(listener)) {
53+
const capture = getCaptureValue(options)
54+
const existingListener = capture ? _captureListenersMap.get(listener) : _nonCaptureListenersMap.get(listener)
55+
56+
// If the listener is already in the map, we don't need to wrap it again
57+
if (existingListener) {
58+
return oldAddEventListener(type, existingListener, options)
59+
}
60+
5261
let newListener
5362

5463
// If the listener is a function, we can just wrap it

packages/server/lib/browsers/browser-cri-client.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,8 @@ export class BrowserCriClient {
322322
try {
323323
// attach a binding to the runtime so that we can listen for service worker fetch events
324324
if (event.targetInfo.type === 'service_worker') {
325-
browserClient.on('Runtime.bindingCalled', serviceWorkerFetchEventHandler(browserCriClient.onServiceWorkerFetch))
325+
// @ts-expect-error - typescript doesn't know about the sessionId specific events
326+
browserClient.on(`Runtime.bindingCalled.${event.sessionId}`, serviceWorkerFetchEventHandler(browserCriClient.onServiceWorkerFetch))
326327
await browserClient.send('Runtime.addBinding', { name: serviceWorkerFetchEventHandlerName }, event.sessionId)
327328
}
328329
} catch (error) {

packages/server/lib/browsers/cdp_automation.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ export class CdpAutomation implements CDPClient {
492492
case 'is:automation:client:connected':
493493
return true
494494
case 'remote:debugger:protocol':
495-
return this.sendDebuggerCommandFn(data.command, data.params)
495+
return this.sendDebuggerCommandFn(data.command, data.params, data.sessionId)
496496
case 'take:screenshot':
497497
return this.sendDebuggerCommandFn('Page.captureScreenshot', { format: 'png' })
498498
.catch((err) => {

0 commit comments

Comments
 (0)