| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Copyright (c) Microsoft Corporation. All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  * you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  * You may obtain a copy of the License at | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  * See the License for the specific language governing permissions and | 
					
						
							|  |  |  |  * limitations under the License. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import fs from 'fs'; | 
					
						
							| 
									
										
										
										
											2024-08-15 08:51:40 +02:00
										 |  |  | import tls from 'tls'; | 
					
						
							| 
									
										
										
										
											2024-08-22 08:42:09 +02:00
										 |  |  | import type https from 'https'; | 
					
						
							|  |  |  | import zlib from 'zlib'; | 
					
						
							| 
									
										
										
										
											2024-07-25 18:53:38 +02:00
										 |  |  | import type http2 from 'http2'; | 
					
						
							| 
									
										
										
										
											2024-07-23 19:18:31 +02:00
										 |  |  | import type http from 'http'; | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  | import { expect, playwrightTest as base } from '../config/browserTest'; | 
					
						
							|  |  |  | import type net from 'net'; | 
					
						
							|  |  |  | import type { BrowserContextOptions } from 'packages/playwright-test'; | 
					
						
							| 
									
										
										
										
											2024-09-16 17:57:33 +02:00
										 |  |  | import { setupSocksForwardingServer } from '../config/proxy'; | 
					
						
							| 
									
										
										
										
											2024-07-25 18:53:38 +02:00
										 |  |  | const { createHttpsServer, createHttp2Server } = require('../../packages/playwright-core/lib/utils'); | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 19:18:31 +02:00
										 |  |  | type TestOptions = { | 
					
						
							|  |  |  |   startCCServer(options?: { | 
					
						
							|  |  |  |     http2?: boolean; | 
					
						
							| 
									
										
										
										
											2024-07-26 11:28:45 +02:00
										 |  |  |     enableHTTP1FallbackWhenUsingHttp2?: boolean; | 
					
						
							| 
									
										
										
										
											2024-07-23 19:18:31 +02:00
										 |  |  |     useFakeLocalhost?: boolean; | 
					
						
							|  |  |  |   }): Promise<string>, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const test = base.extend<TestOptions>({ | 
					
						
							| 
									
										
										
										
											2024-07-25 18:53:38 +02:00
										 |  |  |   startCCServer: async ({ asset }, use) => { | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |     process.env.PWTEST_UNSUPPORTED_CUSTOM_CA = asset('client-certificates/server/server_cert.pem'); | 
					
						
							| 
									
										
										
										
											2024-07-25 18:53:38 +02:00
										 |  |  |     let server: http.Server | http2.Http2SecureServer | undefined; | 
					
						
							| 
									
										
										
										
											2024-07-23 19:18:31 +02:00
										 |  |  |     await use(async options => { | 
					
						
							| 
									
										
										
										
											2024-07-25 18:53:38 +02:00
										 |  |  |       server = (options?.http2 ? createHttp2Server : createHttpsServer)({ | 
					
						
							| 
									
										
										
										
											2024-07-23 19:18:31 +02:00
										 |  |  |         key: fs.readFileSync(asset('client-certificates/server/server_key.pem')), | 
					
						
							|  |  |  |         cert: fs.readFileSync(asset('client-certificates/server/server_cert.pem')), | 
					
						
							|  |  |  |         ca: [ | 
					
						
							|  |  |  |           fs.readFileSync(asset('client-certificates/server/server_cert.pem')), | 
					
						
							|  |  |  |         ], | 
					
						
							|  |  |  |         requestCert: true, | 
					
						
							|  |  |  |         rejectUnauthorized: false, | 
					
						
							| 
									
										
										
										
											2024-07-26 11:28:45 +02:00
										 |  |  |         allowHTTP1: options?.enableHTTP1FallbackWhenUsingHttp2, | 
					
						
							| 
									
										
										
										
											2024-07-23 19:18:31 +02:00
										 |  |  |       }, (req: (http2.Http2ServerRequest | http.IncomingMessage), res: http2.Http2ServerResponse | http.ServerResponse) => { | 
					
						
							|  |  |  |         const tlsSocket = req.socket as import('tls').TLSSocket; | 
					
						
							| 
									
										
										
										
											2024-07-25 18:53:38 +02:00
										 |  |  |         const parts: { key: string, value: any }[] = []; | 
					
						
							|  |  |  |         parts.push({ key: 'alpn-protocol', value: tlsSocket.alpnProtocol }); | 
					
						
							| 
									
										
										
										
											2024-07-23 19:18:31 +02:00
										 |  |  |         // @ts-expect-error https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/62336
 | 
					
						
							| 
									
										
										
										
											2024-07-25 18:53:38 +02:00
										 |  |  |         parts.push({ key: 'servername', value: tlsSocket.servername }); | 
					
						
							| 
									
										
										
										
											2024-07-23 19:18:31 +02:00
										 |  |  |         const cert = tlsSocket.getPeerCertificate(); | 
					
						
							|  |  |  |         if (tlsSocket.authorized) { | 
					
						
							|  |  |  |           res.writeHead(200, { 'Content-Type': 'text/html' }); | 
					
						
							| 
									
										
										
										
											2024-07-25 18:53:38 +02:00
										 |  |  |           parts.push({ key: 'message', value: `Hello ${cert.subject.CN}, your certificate was issued by ${cert.issuer.CN}!` }); | 
					
						
							| 
									
										
										
										
											2024-07-23 19:18:31 +02:00
										 |  |  |         } else if (cert.subject) { | 
					
						
							|  |  |  |           res.writeHead(403, { 'Content-Type': 'text/html' }); | 
					
						
							| 
									
										
										
										
											2024-07-25 18:53:38 +02:00
										 |  |  |           parts.push({ key: 'message', value: `Sorry ${cert.subject.CN}, certificates from ${cert.issuer.CN} are not welcome here.` }); | 
					
						
							| 
									
										
										
										
											2024-07-23 19:18:31 +02:00
										 |  |  |         } else { | 
					
						
							|  |  |  |           res.writeHead(401, { 'Content-Type': 'text/html' }); | 
					
						
							| 
									
										
										
										
											2024-07-25 18:53:38 +02:00
										 |  |  |           parts.push({ key: 'message', value: `Sorry, but you need to provide a client certificate to continue.` }); | 
					
						
							| 
									
										
										
										
											2024-07-23 19:18:31 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-07-25 18:53:38 +02:00
										 |  |  |         res.end(parts.map(({ key, value }) => `<div data-testid="${key}">${value}</div>`).join('')); | 
					
						
							| 
									
										
										
										
											2024-07-23 19:18:31 +02:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2024-09-18 17:09:08 +02:00
										 |  |  |       await new Promise<void>(f => server.listen(0, '127.0.0.1', () => f())); | 
					
						
							|  |  |  |       const host = options?.useFakeLocalhost ? 'local.playwright' : '127.0.0.1'; | 
					
						
							| 
									
										
										
										
											2024-07-23 19:18:31 +02:00
										 |  |  |       return `https://${host}:${(server.address() as net.AddressInfo).port}/`; | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-07-24 11:39:39 +02:00
										 |  |  |     if (server) | 
					
						
							|  |  |  |       await new Promise<void>(resolve => server.close(() => resolve())); | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |   }, | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const kDummyFileName = __filename; | 
					
						
							|  |  |  | const kValidationSubTests: [BrowserContextOptions, string][] = [ | 
					
						
							| 
									
										
										
										
											2024-07-23 22:56:36 +02:00
										 |  |  |   [{ clientCertificates: [{ origin: 'test' }] }, 'None of cert, key, passphrase or pfx is specified'], | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |   [{ | 
					
						
							|  |  |  |     clientCertificates: [{ | 
					
						
							| 
									
										
										
										
											2024-07-23 22:56:36 +02:00
										 |  |  |       origin: 'test', | 
					
						
							|  |  |  |       certPath: kDummyFileName, | 
					
						
							|  |  |  |       keyPath: kDummyFileName, | 
					
						
							|  |  |  |       pfxPath: kDummyFileName, | 
					
						
							|  |  |  |       passphrase: kDummyFileName, | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |     }] | 
					
						
							|  |  |  |   }, 'pfx is specified together with cert, key or passphrase'], | 
					
						
							|  |  |  | ]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | test.describe('fetch', () => { | 
					
						
							|  |  |  |   test('validate input', async ({ playwright }) => { | 
					
						
							|  |  |  |     for (const [contextOptions, expected] of kValidationSubTests) | 
					
						
							|  |  |  |       await expect(playwright.request.newContext(contextOptions)).rejects.toThrow(expected); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 19:18:31 +02:00
										 |  |  |   test('should fail with no client certificates provided', async ({ playwright, startCCServer }) => { | 
					
						
							|  |  |  |     const serverURL = await startCCServer(); | 
					
						
							| 
									
										
										
										
											2024-08-02 08:34:28 +02:00
										 |  |  |     const request = await playwright.request.newContext({ ignoreHTTPSErrors: true }); | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |     const response = await request.get(serverURL); | 
					
						
							|  |  |  |     expect(response.status()).toBe(401); | 
					
						
							| 
									
										
										
										
											2024-07-24 11:39:39 +02:00
										 |  |  |     expect(await response.text()).toContain('Sorry, but you need to provide a client certificate to continue.'); | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |     await request.dispose(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   test('should keep supporting http', async ({ playwright, server, asset }) => { | 
					
						
							|  |  |  |     const request = await playwright.request.newContext({ | 
					
						
							| 
									
										
										
										
											2024-08-02 08:34:28 +02:00
										 |  |  |       ignoreHTTPSErrors: true, | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |       clientCertificates: [{ | 
					
						
							| 
									
										
										
										
											2024-07-23 22:56:36 +02:00
										 |  |  |         origin: new URL(server.PREFIX).origin, | 
					
						
							|  |  |  |         certPath: asset('client-certificates/client/trusted/cert.pem'), | 
					
						
							|  |  |  |         keyPath: asset('client-certificates/client/trusted/key.pem'), | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |       }], | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     const response = await request.get(server.PREFIX + '/one-style.html'); | 
					
						
							|  |  |  |     expect(response.url()).toBe(server.PREFIX + '/one-style.html'); | 
					
						
							|  |  |  |     expect(response.status()).toBe(200); | 
					
						
							|  |  |  |     expect(await response.text()).toContain('<div>hello, world!</div>'); | 
					
						
							|  |  |  |     await request.dispose(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 19:18:31 +02:00
										 |  |  |   test('should throw with untrusted client certs', async ({ playwright, startCCServer, asset }) => { | 
					
						
							|  |  |  |     const serverURL = await startCCServer(); | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |     const request = await playwright.request.newContext({ | 
					
						
							| 
									
										
										
										
											2024-08-02 08:34:28 +02:00
										 |  |  |       ignoreHTTPSErrors: true, | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |       clientCertificates: [{ | 
					
						
							| 
									
										
										
										
											2024-07-23 22:56:36 +02:00
										 |  |  |         origin: new URL(serverURL).origin, | 
					
						
							|  |  |  |         certPath: asset('client-certificates/client/self-signed/cert.pem'), | 
					
						
							|  |  |  |         keyPath: asset('client-certificates/client/self-signed/key.pem'), | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |       }], | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     const response = await request.get(serverURL); | 
					
						
							|  |  |  |     expect(response.url()).toBe(serverURL); | 
					
						
							|  |  |  |     expect(response.status()).toBe(403); | 
					
						
							| 
									
										
										
										
											2024-07-24 11:39:39 +02:00
										 |  |  |     expect(await response.text()).toContain('Sorry Bob, certificates from Bob are not welcome here.'); | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |     await request.dispose(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 19:18:31 +02:00
										 |  |  |   test('pass with trusted client certificates', async ({ playwright, startCCServer, asset }) => { | 
					
						
							|  |  |  |     const serverURL = await startCCServer(); | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |     const request = await playwright.request.newContext({ | 
					
						
							| 
									
										
										
										
											2024-08-02 08:34:28 +02:00
										 |  |  |       ignoreHTTPSErrors: true, | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |       clientCertificates: [{ | 
					
						
							| 
									
										
										
										
											2024-07-23 22:56:36 +02:00
										 |  |  |         origin: new URL(serverURL).origin, | 
					
						
							|  |  |  |         certPath: asset('client-certificates/client/trusted/cert.pem'), | 
					
						
							|  |  |  |         keyPath: asset('client-certificates/client/trusted/key.pem'), | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |       }], | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     const response = await request.get(serverURL); | 
					
						
							|  |  |  |     expect(response.url()).toBe(serverURL); | 
					
						
							|  |  |  |     expect(response.status()).toBe(200); | 
					
						
							| 
									
										
										
										
											2024-07-24 11:39:39 +02:00
										 |  |  |     expect(await response.text()).toContain('Hello Alice, your certificate was issued by localhost!'); | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |     await request.dispose(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-05 14:42:29 +02:00
										 |  |  |   test('pass with trusted client certificates in pfx format', async ({ playwright, startCCServer, asset }) => { | 
					
						
							|  |  |  |     const serverURL = await startCCServer(); | 
					
						
							|  |  |  |     const request = await playwright.request.newContext({ | 
					
						
							|  |  |  |       ignoreHTTPSErrors: true, | 
					
						
							|  |  |  |       clientCertificates: [{ | 
					
						
							|  |  |  |         origin: new URL(serverURL).origin, | 
					
						
							|  |  |  |         pfxPath: asset('client-certificates/client/trusted/cert.pfx'), | 
					
						
							|  |  |  |         passphrase: 'secure' | 
					
						
							|  |  |  |       }], | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     const response = await request.get(serverURL); | 
					
						
							|  |  |  |     expect(response.url()).toBe(serverURL); | 
					
						
							|  |  |  |     expect(response.status()).toBe(200); | 
					
						
							|  |  |  |     expect(await response.text()).toContain('Hello Alice, your certificate was issued by localhost!'); | 
					
						
							|  |  |  |     await request.dispose(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-16 17:57:33 +02:00
										 |  |  |   test('pass with trusted client certificates and when a http proxy is used', async ({ playwright, startCCServer, proxyServer, asset }) => { | 
					
						
							|  |  |  |     const serverURL = await startCCServer(); | 
					
						
							|  |  |  |     proxyServer.forwardTo(parseInt(new URL(serverURL).port, 10), { allowConnectRequests: true }); | 
					
						
							|  |  |  |     const request = await playwright.request.newContext({ | 
					
						
							|  |  |  |       ignoreHTTPSErrors: true, | 
					
						
							|  |  |  |       clientCertificates: [{ | 
					
						
							|  |  |  |         origin: new URL(serverURL).origin, | 
					
						
							|  |  |  |         certPath: asset('client-certificates/client/trusted/cert.pem'), | 
					
						
							|  |  |  |         keyPath: asset('client-certificates/client/trusted/key.pem'), | 
					
						
							|  |  |  |       }], | 
					
						
							|  |  |  |       proxy: { server: `localhost:${proxyServer.PORT}` } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     expect(proxyServer.connectHosts).toEqual([]); | 
					
						
							|  |  |  |     const response = await request.get(serverURL); | 
					
						
							|  |  |  |     expect(proxyServer.connectHosts).toEqual([new URL(serverURL).host]); | 
					
						
							|  |  |  |     expect(response.url()).toBe(serverURL); | 
					
						
							|  |  |  |     expect(response.status()).toBe(200); | 
					
						
							|  |  |  |     expect(await response.text()).toContain('Hello Alice, your certificate was issued by localhost!'); | 
					
						
							|  |  |  |     await request.dispose(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   test('pass with trusted client certificates and when a socks proxy is used', async ({ playwright, startCCServer, asset }) => { | 
					
						
							| 
									
										
										
										
											2024-09-18 17:09:08 +02:00
										 |  |  |     const serverURL = await startCCServer(); | 
					
						
							| 
									
										
										
										
											2024-09-16 17:57:33 +02:00
										 |  |  |     const serverPort = parseInt(new URL(serverURL).port, 10); | 
					
						
							|  |  |  |     const { proxyServerAddr, closeProxyServer, connectHosts } = await setupSocksForwardingServer({ | 
					
						
							|  |  |  |       port: test.info().workerIndex + 2048 + 2, | 
					
						
							|  |  |  |       forwardPort: serverPort, | 
					
						
							|  |  |  |       allowedTargetPort: serverPort, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     const request = await playwright.request.newContext({ | 
					
						
							|  |  |  |       ignoreHTTPSErrors: true, | 
					
						
							|  |  |  |       clientCertificates: [{ | 
					
						
							|  |  |  |         origin: new URL(serverURL).origin, | 
					
						
							|  |  |  |         certPath: asset('client-certificates/client/trusted/cert.pem'), | 
					
						
							|  |  |  |         keyPath: asset('client-certificates/client/trusted/key.pem'), | 
					
						
							|  |  |  |       }], | 
					
						
							|  |  |  |       proxy: { server: proxyServerAddr } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     expect(connectHosts).toEqual([]); | 
					
						
							|  |  |  |     const response = await request.get(serverURL); | 
					
						
							|  |  |  |     expect(connectHosts).toEqual([new URL(serverURL).host]); | 
					
						
							|  |  |  |     expect(response.url()).toBe(serverURL); | 
					
						
							|  |  |  |     expect(response.status()).toBe(200); | 
					
						
							|  |  |  |     expect(await response.text()).toContain('Hello Alice, your certificate was issued by localhost!'); | 
					
						
							|  |  |  |     await request.dispose(); | 
					
						
							|  |  |  |     await closeProxyServer(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-05 14:42:29 +02:00
										 |  |  |   test('should throw a http error if the pfx passphrase is incorect', async ({ playwright, startCCServer, asset, browserName }) => { | 
					
						
							| 
									
										
										
										
											2024-08-06 08:46:35 +02:00
										 |  |  |     const serverURL = await startCCServer(); | 
					
						
							| 
									
										
										
										
											2024-08-05 14:42:29 +02:00
										 |  |  |     const request = await playwright.request.newContext({ | 
					
						
							|  |  |  |       ignoreHTTPSErrors: true, | 
					
						
							|  |  |  |       clientCertificates: [{ | 
					
						
							|  |  |  |         origin: new URL(serverURL).origin, | 
					
						
							|  |  |  |         pfxPath: asset('client-certificates/client/trusted/cert.pfx'), | 
					
						
							|  |  |  |         passphrase: 'this-password-is-incorrect' | 
					
						
							|  |  |  |       }], | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     await expect(request.get(serverURL)).rejects.toThrow('mac verify failure'); | 
					
						
							|  |  |  |     await request.dispose(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   test('should fail with matching certificates in legacy pfx format', async ({ playwright, startCCServer, asset, browserName }) => { | 
					
						
							| 
									
										
										
										
											2024-08-06 08:46:35 +02:00
										 |  |  |     const serverURL = await startCCServer(); | 
					
						
							| 
									
										
										
										
											2024-08-05 14:42:29 +02:00
										 |  |  |     const request = await playwright.request.newContext({ | 
					
						
							|  |  |  |       ignoreHTTPSErrors: true, | 
					
						
							|  |  |  |       clientCertificates: [{ | 
					
						
							|  |  |  |         origin: new URL(serverURL).origin, | 
					
						
							|  |  |  |         pfxPath: asset('client-certificates/client/trusted/cert-legacy.pfx'), | 
					
						
							|  |  |  |         passphrase: 'secure' | 
					
						
							|  |  |  |       }], | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     await expect(request.get(serverURL)).rejects.toThrow('Unsupported TLS certificate'); | 
					
						
							|  |  |  |     await request.dispose(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-23 19:18:31 +02:00
										 |  |  |   test('should work in the browser with request interception', async ({ browser, playwright, startCCServer, asset }) => { | 
					
						
							|  |  |  |     const serverURL = await startCCServer(); | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |     const request = await playwright.request.newContext({ | 
					
						
							| 
									
										
										
										
											2024-08-02 08:34:28 +02:00
										 |  |  |       ignoreHTTPSErrors: true, | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |       clientCertificates: [{ | 
					
						
							| 
									
										
										
										
											2024-07-23 22:56:36 +02:00
										 |  |  |         origin: new URL(serverURL).origin, | 
					
						
							|  |  |  |         certPath: asset('client-certificates/client/trusted/cert.pem'), | 
					
						
							|  |  |  |         keyPath: asset('client-certificates/client/trusted/key.pem'), | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |       }], | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     const page = await browser.newPage({ ignoreHTTPSErrors: true }); | 
					
						
							|  |  |  |     await page.route('**/*', async route => { | 
					
						
							|  |  |  |       const response = await request.fetch(route.request()); | 
					
						
							|  |  |  |       await route.fulfill({ response }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     await page.goto(serverURL); | 
					
						
							| 
									
										
										
										
											2024-07-25 18:53:38 +02:00
										 |  |  |     await expect(page.getByTestId('message')).toHaveText('Hello Alice, your certificate was issued by localhost!'); | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |     await page.close(); | 
					
						
							|  |  |  |     await request.dispose(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | test.describe('browser', () => { | 
					
						
							|  |  |  |   test('validate input', async ({ browser }) => { | 
					
						
							|  |  |  |     for (const [contextOptions, expected] of kValidationSubTests) | 
					
						
							|  |  |  |       await expect(browser.newContext(contextOptions)).rejects.toThrow(expected); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   test('should keep supporting http', async ({ browser, server, asset }) => { | 
					
						
							|  |  |  |     const page = await browser.newPage({ | 
					
						
							|  |  |  |       clientCertificates: [{ | 
					
						
							| 
									
										
										
										
											2024-07-23 22:56:36 +02:00
										 |  |  |         origin: new URL(server.PREFIX).origin, | 
					
						
							|  |  |  |         certPath: asset('client-certificates/client/trusted/cert.pem'), | 
					
						
							|  |  |  |         keyPath: asset('client-certificates/client/trusted/key.pem'), | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |       }], | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     await page.goto(server.PREFIX + '/one-style.html'); | 
					
						
							|  |  |  |     await expect(page.getByText('hello, world!')).toBeVisible(); | 
					
						
							|  |  |  |     await expect(page.locator('body')).toHaveCSS('background-color', 'rgb(255, 192, 203)'); | 
					
						
							|  |  |  |     await page.close(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-27 07:06:37 -07:00
										 |  |  |   test('should fail with no client certificates', async ({ browser, startCCServer, asset, browserName, isMac }) => { | 
					
						
							|  |  |  |     const serverURL = await startCCServer({ useFakeLocalhost: browserName === 'webkit' && isMac }); | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |     const page = await browser.newPage({ | 
					
						
							| 
									
										
										
										
											2024-08-02 08:34:28 +02:00
										 |  |  |       ignoreHTTPSErrors: true, | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |       clientCertificates: [{ | 
					
						
							| 
									
										
										
										
											2024-07-23 22:56:36 +02:00
										 |  |  |         origin: 'https://not-matching.com', | 
					
						
							|  |  |  |         certPath: asset('client-certificates/client/trusted/cert.pem'), | 
					
						
							|  |  |  |         keyPath: asset('client-certificates/client/trusted/key.pem'), | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |       }], | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-07-23 19:18:31 +02:00
										 |  |  |     await page.goto(serverURL); | 
					
						
							| 
									
										
										
										
											2024-07-25 18:53:38 +02:00
										 |  |  |     await expect(page.getByTestId('message')).toHaveText('Sorry, but you need to provide a client certificate to continue.'); | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |     await page.close(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-27 07:06:37 -07:00
										 |  |  |   test('should fail with self-signed client certificates', async ({ browser, startCCServer, asset, browserName, isMac }) => { | 
					
						
							|  |  |  |     const serverURL = await startCCServer({ useFakeLocalhost: browserName === 'webkit' && isMac }); | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |     const page = await browser.newPage({ | 
					
						
							| 
									
										
										
										
											2024-08-02 08:34:28 +02:00
										 |  |  |       ignoreHTTPSErrors: true, | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |       clientCertificates: [{ | 
					
						
							| 
									
										
										
										
											2024-07-23 22:56:36 +02:00
										 |  |  |         origin: new URL(serverURL).origin, | 
					
						
							|  |  |  |         certPath: asset('client-certificates/client/self-signed/cert.pem'), | 
					
						
							|  |  |  |         keyPath: asset('client-certificates/client/self-signed/key.pem'), | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |       }], | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-07-23 19:18:31 +02:00
										 |  |  |     await page.goto(serverURL); | 
					
						
							| 
									
										
										
										
											2024-07-25 18:53:38 +02:00
										 |  |  |     await expect(page.getByTestId('message')).toHaveText('Sorry Bob, certificates from Bob are not welcome here.'); | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |     await page.close(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-27 07:06:37 -07:00
										 |  |  |   test('should pass with matching certificates', async ({ browser, startCCServer, asset, browserName, isMac }) => { | 
					
						
							|  |  |  |     const serverURL = await startCCServer({ useFakeLocalhost: browserName === 'webkit' && isMac }); | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |     const page = await browser.newPage({ | 
					
						
							| 
									
										
										
										
											2024-08-02 08:34:28 +02:00
										 |  |  |       ignoreHTTPSErrors: true, | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |       clientCertificates: [{ | 
					
						
							| 
									
										
										
										
											2024-07-23 22:56:36 +02:00
										 |  |  |         origin: new URL(serverURL).origin, | 
					
						
							|  |  |  |         certPath: asset('client-certificates/client/trusted/cert.pem'), | 
					
						
							|  |  |  |         keyPath: asset('client-certificates/client/trusted/key.pem'), | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |       }], | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-07-23 19:18:31 +02:00
										 |  |  |     await page.goto(serverURL); | 
					
						
							| 
									
										
										
										
											2024-07-25 18:53:38 +02:00
										 |  |  |     await expect(page.getByTestId('message')).toHaveText('Hello Alice, your certificate was issued by localhost!'); | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |     await page.close(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-27 07:06:37 -07:00
										 |  |  |   test('should pass with matching certificates when passing as content', async ({ browser, startCCServer, asset, browserName, isMac }) => { | 
					
						
							|  |  |  |     const serverURL = await startCCServer({ useFakeLocalhost: browserName === 'webkit' && isMac }); | 
					
						
							| 
									
										
										
										
											2024-08-19 09:24:32 +02:00
										 |  |  |     const page = await browser.newPage({ | 
					
						
							|  |  |  |       ignoreHTTPSErrors: true, | 
					
						
							|  |  |  |       clientCertificates: [{ | 
					
						
							|  |  |  |         origin: new URL(serverURL).origin, | 
					
						
							|  |  |  |         cert: await fs.promises.readFile(asset('client-certificates/client/trusted/cert.pem')), | 
					
						
							|  |  |  |         key: await fs.promises.readFile(asset('client-certificates/client/trusted/key.pem')), | 
					
						
							|  |  |  |       }], | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     await page.goto(serverURL); | 
					
						
							|  |  |  |     await expect(page.getByTestId('message')).toHaveText('Hello Alice, your certificate was issued by localhost!'); | 
					
						
							|  |  |  |     await page.close(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-27 07:06:37 -07:00
										 |  |  |   test('should pass with matching certificates and when a http proxy is used', async ({ browser, startCCServer, asset, browserName, proxyServer, isMac }) => { | 
					
						
							|  |  |  |     const serverURL = await startCCServer({ useFakeLocalhost: browserName === 'webkit' && isMac }); | 
					
						
							| 
									
										
										
										
											2024-09-16 17:57:33 +02:00
										 |  |  |     proxyServer.forwardTo(parseInt(new URL(serverURL).port, 10), { allowConnectRequests: true }); | 
					
						
							|  |  |  |     const page = await browser.newPage({ | 
					
						
							|  |  |  |       ignoreHTTPSErrors: true, | 
					
						
							|  |  |  |       clientCertificates: [{ | 
					
						
							|  |  |  |         origin: new URL(serverURL).origin, | 
					
						
							|  |  |  |         certPath: asset('client-certificates/client/trusted/cert.pem'), | 
					
						
							|  |  |  |         keyPath: asset('client-certificates/client/trusted/key.pem'), | 
					
						
							|  |  |  |       }], | 
					
						
							|  |  |  |       proxy: { server: `localhost:${proxyServer.PORT}` } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     expect(proxyServer.connectHosts).toEqual([]); | 
					
						
							|  |  |  |     await page.goto(serverURL); | 
					
						
							| 
									
										
										
										
											2024-09-27 07:06:37 -07:00
										 |  |  |     const host = browserName === 'webkit' && isMac ? 'localhost' : '127.0.0.1'; | 
					
						
							| 
									
										
										
										
											2024-09-19 12:03:05 +02:00
										 |  |  |     expect([...new Set(proxyServer.connectHosts)]).toEqual([`${host}:${new URL(serverURL).port}`]); | 
					
						
							| 
									
										
										
										
											2024-09-16 17:57:33 +02:00
										 |  |  |     await expect(page.getByTestId('message')).toHaveText('Hello Alice, your certificate was issued by localhost!'); | 
					
						
							|  |  |  |     await page.close(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-27 07:06:37 -07:00
										 |  |  |   test('should pass with matching certificates and when a socks proxy is used', async ({ browser, startCCServer, asset, browserName, isMac }) => { | 
					
						
							|  |  |  |     const serverURL = await startCCServer({ useFakeLocalhost: browserName === 'webkit' && isMac }); | 
					
						
							| 
									
										
										
										
											2024-09-16 17:57:33 +02:00
										 |  |  |     const serverPort = parseInt(new URL(serverURL).port, 10); | 
					
						
							|  |  |  |     const { proxyServerAddr, closeProxyServer, connectHosts } = await setupSocksForwardingServer({ | 
					
						
							|  |  |  |       port: test.info().workerIndex + 2048 + 2, | 
					
						
							|  |  |  |       forwardPort: serverPort, | 
					
						
							|  |  |  |       allowedTargetPort: serverPort, | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     const page = await browser.newPage({ | 
					
						
							|  |  |  |       ignoreHTTPSErrors: true, | 
					
						
							|  |  |  |       clientCertificates: [{ | 
					
						
							|  |  |  |         origin: new URL(serverURL).origin, | 
					
						
							|  |  |  |         certPath: asset('client-certificates/client/trusted/cert.pem'), | 
					
						
							|  |  |  |         keyPath: asset('client-certificates/client/trusted/key.pem'), | 
					
						
							|  |  |  |       }], | 
					
						
							|  |  |  |       proxy: { server: proxyServerAddr } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     expect(connectHosts).toEqual([]); | 
					
						
							|  |  |  |     await page.goto(serverURL); | 
					
						
							| 
									
										
										
										
											2025-01-29 14:51:31 +00:00
										 |  |  |     const host = browserName === 'webkit' && isMac ? 'localhost' : '127.0.0.1'; | 
					
						
							| 
									
										
										
										
											2024-09-19 12:03:05 +02:00
										 |  |  |     expect(connectHosts).toEqual([`${host}:${serverPort}`]); | 
					
						
							| 
									
										
										
										
											2024-09-16 17:57:33 +02:00
										 |  |  |     await expect(page.getByTestId('message')).toHaveText('Hello Alice, your certificate was issued by localhost!'); | 
					
						
							|  |  |  |     await page.close(); | 
					
						
							|  |  |  |     await closeProxyServer(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-15 08:51:40 +02:00
										 |  |  |   test('should not hang on tls errors during TLS 1.2 handshake', async ({ browser, asset, platform, browserName }) => { | 
					
						
							|  |  |  |     for (const tlsVersion of ['TLSv1.3', 'TLSv1.2'] as const) { | 
					
						
							|  |  |  |       await test.step(`TLS version: ${tlsVersion}`, async () => { | 
					
						
							|  |  |  |         const server = tls.createServer({ | 
					
						
							|  |  |  |           key: fs.readFileSync(asset('client-certificates/server/server_key.pem')), | 
					
						
							|  |  |  |           cert: fs.readFileSync(asset('client-certificates/server/server_cert.pem')), | 
					
						
							|  |  |  |           ca: [ | 
					
						
							|  |  |  |             fs.readFileSync(asset('client-certificates/server/server_cert.pem')), | 
					
						
							|  |  |  |           ], | 
					
						
							|  |  |  |           requestCert: true, | 
					
						
							|  |  |  |           rejectUnauthorized: true, | 
					
						
							|  |  |  |           minVersion: tlsVersion, | 
					
						
							|  |  |  |           maxVersion: tlsVersion, | 
					
						
							|  |  |  |           SNICallback: (servername, cb) => { | 
					
						
							|  |  |  |             // Always reject the connection by passing an error
 | 
					
						
							|  |  |  |             cb(new Error('Connection rejected'), null); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }, () => { | 
					
						
							|  |  |  |           // Do nothing
 | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         const serverURL = await new Promise<string>(resolve => { | 
					
						
							|  |  |  |           server.listen(0, 'localhost', () => { | 
					
						
							|  |  |  |             const host = browserName === 'webkit' && platform === 'darwin' ? 'local.playwright' : 'localhost'; | 
					
						
							|  |  |  |             resolve(`https://${host}:${(server.address() as net.AddressInfo).port}/`); | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         const page = await browser.newPage({ | 
					
						
							|  |  |  |           ignoreHTTPSErrors: true, | 
					
						
							|  |  |  |           clientCertificates: [{ | 
					
						
							|  |  |  |             origin: new URL(serverURL).origin, | 
					
						
							|  |  |  |             certPath: asset('client-certificates/client/self-signed/cert.pem'), | 
					
						
							|  |  |  |             keyPath: asset('client-certificates/client/self-signed/key.pem'), | 
					
						
							|  |  |  |           }], | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         await page.goto(serverURL); | 
					
						
							|  |  |  |         await expect(page.getByText('Playwright client-certificate error: Client network socket disconnected before secure TLS connection was established')).toBeVisible(); | 
					
						
							|  |  |  |         await page.close(); | 
					
						
							|  |  |  |         await new Promise<void>(resolve => server.close(() => resolve())); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-27 07:06:37 -07:00
										 |  |  |   test('should pass with matching certificates in pfx format', async ({ browser, startCCServer, asset, browserName, isMac }) => { | 
					
						
							|  |  |  |     const serverURL = await startCCServer({ useFakeLocalhost: browserName === 'webkit' && isMac }); | 
					
						
							| 
									
										
										
										
											2024-08-05 10:54:33 +02:00
										 |  |  |     const page = await browser.newPage({ | 
					
						
							|  |  |  |       ignoreHTTPSErrors: true, | 
					
						
							|  |  |  |       clientCertificates: [{ | 
					
						
							|  |  |  |         origin: new URL(serverURL).origin, | 
					
						
							|  |  |  |         pfxPath: asset('client-certificates/client/trusted/cert.pfx'), | 
					
						
							|  |  |  |         passphrase: 'secure' | 
					
						
							|  |  |  |       }], | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     await page.goto(serverURL); | 
					
						
							|  |  |  |     await expect(page.getByTestId('message')).toHaveText('Hello Alice, your certificate was issued by localhost!'); | 
					
						
							|  |  |  |     await page.close(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-22 08:42:09 +02:00
										 |  |  |   test('should handle TLS renegotiation with client certificates', async ({ browser, asset, browserName, platform }) => { | 
					
						
							|  |  |  |     const server: https.Server = createHttpsServer({ | 
					
						
							|  |  |  |       key: fs.readFileSync(asset('client-certificates/server/server_key.pem')), | 
					
						
							|  |  |  |       cert: fs.readFileSync(asset('client-certificates/server/server_cert.pem')), | 
					
						
							|  |  |  |       ca: [fs.readFileSync(asset('client-certificates/server/server_cert.pem'))], | 
					
						
							|  |  |  |       requestCert: false, // Initially don't request client cert
 | 
					
						
							|  |  |  |       rejectUnauthorized: false, | 
					
						
							|  |  |  |       // TLSv1.3 does not support renegotiation
 | 
					
						
							|  |  |  |       minVersion: 'TLSv1.2', | 
					
						
							|  |  |  |       maxVersion: 'TLSv1.2', | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     server.on('request', async (req, res) => { | 
					
						
							|  |  |  |       if (!req.socket) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       const renegotiate = () => new Promise<void>((resolve, reject) => { | 
					
						
							|  |  |  |         (req.socket as tls.TLSSocket).renegotiate({ | 
					
						
							|  |  |  |           requestCert: true, | 
					
						
							|  |  |  |           rejectUnauthorized: false | 
					
						
							|  |  |  |         }, err => { | 
					
						
							|  |  |  |           if (err) | 
					
						
							|  |  |  |             reject(err); | 
					
						
							|  |  |  |           else | 
					
						
							|  |  |  |             resolve(); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       if (req.url === '/') { | 
					
						
							|  |  |  |         res.writeHead(200, { 'Content-Type': 'text/html', 'connection': 'close' }); | 
					
						
							|  |  |  |         res.end(); | 
					
						
							|  |  |  |       } else if (req.url === '/from-fetch-api') { | 
					
						
							|  |  |  |         res.writeHead(200, { | 
					
						
							|  |  |  |           'Content-Type': 'text/plain', | 
					
						
							|  |  |  |           'Transfer-Encoding': 'chunked' | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         res.flushHeaders(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await new Promise<void>(resolve => req.once('data', data => { | 
					
						
							|  |  |  |           res.write(`server received: ${data.toString()}\n`); | 
					
						
							|  |  |  |           resolve(); | 
					
						
							|  |  |  |         })); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await renegotiate(); | 
					
						
							|  |  |  |         for (let i = 0; i < 4; i++) { | 
					
						
							|  |  |  |           res.write(`${i}-from-server\n`); | 
					
						
							|  |  |  |           // Best-effort to trigger a new chunk
 | 
					
						
							|  |  |  |           await new Promise<void>(resolve => setTimeout(resolve, 100)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         res.end('server closed the connection'); | 
					
						
							|  |  |  |       } else if (req.url === '/style.css') { | 
					
						
							|  |  |  |         res.writeHead(200, { | 
					
						
							|  |  |  |           'Content-Type': 'text/css', | 
					
						
							|  |  |  |           'Content-Encoding': 'gzip', | 
					
						
							|  |  |  |           'Transfer-Encoding': 'chunked' | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await renegotiate(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const stylesheet = `
 | 
					
						
							|  |  |  |           button { | 
					
						
							|  |  |  |             background-color: red; | 
					
						
							| 
									
										
										
										
											2024-09-27 07:06:37 -07:00
										 |  |  |           } | 
					
						
							| 
									
										
										
										
											2024-08-22 08:42:09 +02:00
										 |  |  |         `;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const stylesheetBuffer = await new Promise<Buffer>((resolve, reject) => { | 
					
						
							|  |  |  |           zlib.gzip(stylesheet, (err, buffer) => { | 
					
						
							|  |  |  |             if (err) | 
					
						
							|  |  |  |               reject(err); | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |               resolve(buffer); | 
					
						
							|  |  |  |           }); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         for (let i = 0; i < stylesheetBuffer.length; i += 100) { | 
					
						
							|  |  |  |           res.write(stylesheetBuffer.slice(i, i + 100)); | 
					
						
							|  |  |  |           // Best-effort to trigger a new chunk
 | 
					
						
							|  |  |  |           await new Promise<void>(resolve => setTimeout(resolve, 20)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         res.end(); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         res.writeHead(404); | 
					
						
							|  |  |  |         res.end(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     await new Promise<void>(resolve => server.listen(0, 'localhost', resolve)); | 
					
						
							| 
									
										
										
										
											2024-08-22 15:13:54 +02:00
										 |  |  |     const port = (server.address() as net.AddressInfo).port; | 
					
						
							| 
									
										
										
										
											2024-08-22 08:42:09 +02:00
										 |  |  |     const origin = 'https://' + (browserName === 'webkit' && platform === 'darwin' ? 'local.playwright' : 'localhost'); | 
					
						
							|  |  |  |     const serverUrl = `${origin}:${port}`; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const context = await browser.newContext({ | 
					
						
							|  |  |  |       ignoreHTTPSErrors: true, | 
					
						
							|  |  |  |       clientCertificates: [{ | 
					
						
							|  |  |  |         origin, | 
					
						
							|  |  |  |         certPath: asset('client-certificates/client/trusted/cert.pem'), | 
					
						
							|  |  |  |         keyPath: asset('client-certificates/client/trusted/key.pem'), | 
					
						
							|  |  |  |       }], | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const page = await context.newPage(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     await test.step('fetch API', async () => { | 
					
						
							|  |  |  |       await page.goto(serverUrl); | 
					
						
							|  |  |  |       const response = await page.evaluate(async () => { | 
					
						
							|  |  |  |         const response = await fetch('/from-fetch-api', { | 
					
						
							|  |  |  |           method: 'POST', | 
					
						
							|  |  |  |           body: 'client-request-payload' | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |         return await response.text(); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       expect(response).toBe([ | 
					
						
							|  |  |  |         'server received: client-request-payload', | 
					
						
							|  |  |  |         '0-from-server', | 
					
						
							|  |  |  |         '1-from-server', | 
					
						
							|  |  |  |         '2-from-server', | 
					
						
							|  |  |  |         '3-from-server', | 
					
						
							|  |  |  |         'server closed the connection' | 
					
						
							|  |  |  |       ].join('\n')); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     await test.step('Gzip encoded CSS Stylesheet', async () => { | 
					
						
							|  |  |  |       await page.goto(serverUrl); | 
					
						
							|  |  |  |       // The <link> would throw with net::ERR_INVALID_CHUNKED_ENCODING
 | 
					
						
							|  |  |  |       await page.setContent(`
 | 
					
						
							|  |  |  |         <button>Click me</button> | 
					
						
							|  |  |  |         <link rel="stylesheet" href="/style.css"> | 
					
						
							|  |  |  |       `);
 | 
					
						
							|  |  |  |       await expect(page.locator('button')).toHaveCSS('background-color', /* red */'rgb(255, 0, 0)'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     await context.close(); | 
					
						
							|  |  |  |     await new Promise<void>(resolve => server.close(() => resolve())); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-27 07:06:37 -07:00
										 |  |  |   test('should pass with matching certificates in pfx format when passing as content', async ({ browser, startCCServer, asset, browserName, isMac }) => { | 
					
						
							|  |  |  |     const serverURL = await startCCServer({ useFakeLocalhost: browserName === 'webkit' && isMac }); | 
					
						
							| 
									
										
										
										
											2024-08-19 09:24:32 +02:00
										 |  |  |     const page = await browser.newPage({ | 
					
						
							|  |  |  |       ignoreHTTPSErrors: true, | 
					
						
							|  |  |  |       clientCertificates: [{ | 
					
						
							|  |  |  |         origin: new URL(serverURL).origin, | 
					
						
							|  |  |  |         pfx: await fs.promises.readFile(asset('client-certificates/client/trusted/cert.pfx')), | 
					
						
							|  |  |  |         passphrase: 'secure' | 
					
						
							|  |  |  |       }], | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     await page.goto(serverURL); | 
					
						
							|  |  |  |     await expect(page.getByTestId('message')).toHaveText('Hello Alice, your certificate was issued by localhost!'); | 
					
						
							|  |  |  |     await page.close(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-27 07:06:37 -07:00
										 |  |  |   test('should fail with matching certificates in legacy pfx format', async ({ browser, startCCServer, asset, browserName, isMac }) => { | 
					
						
							|  |  |  |     const serverURL = await startCCServer({ useFakeLocalhost: browserName === 'webkit' && isMac }); | 
					
						
							| 
									
										
										
										
											2024-08-19 09:02:14 +02:00
										 |  |  |     await expect(browser.newPage({ | 
					
						
							| 
									
										
										
										
											2024-08-05 14:42:29 +02:00
										 |  |  |       ignoreHTTPSErrors: true, | 
					
						
							|  |  |  |       clientCertificates: [{ | 
					
						
							|  |  |  |         origin: new URL(serverURL).origin, | 
					
						
							|  |  |  |         pfxPath: asset('client-certificates/client/trusted/cert-legacy.pfx'), | 
					
						
							|  |  |  |         passphrase: 'secure' | 
					
						
							|  |  |  |       }], | 
					
						
							| 
									
										
										
										
											2024-08-19 09:02:14 +02:00
										 |  |  |     })).rejects.toThrow('Unsupported TLS certificate'); | 
					
						
							| 
									
										
										
										
											2024-08-05 14:42:29 +02:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-27 07:06:37 -07:00
										 |  |  |   test('should throw a http error if the pfx passphrase is incorect', async ({ browser, startCCServer, asset, browserName, isMac }) => { | 
					
						
							|  |  |  |     const serverURL = await startCCServer({ useFakeLocalhost: browserName === 'webkit' && isMac }); | 
					
						
							| 
									
										
										
										
											2024-08-19 09:02:14 +02:00
										 |  |  |     await expect(browser.newPage({ | 
					
						
							| 
									
										
										
										
											2024-08-05 10:54:33 +02:00
										 |  |  |       ignoreHTTPSErrors: true, | 
					
						
							|  |  |  |       clientCertificates: [{ | 
					
						
							|  |  |  |         origin: new URL(serverURL).origin, | 
					
						
							|  |  |  |         pfxPath: asset('client-certificates/client/trusted/cert.pfx'), | 
					
						
							|  |  |  |         passphrase: 'this-password-is-incorrect' | 
					
						
							|  |  |  |       }], | 
					
						
							| 
									
										
										
										
											2024-08-19 09:02:14 +02:00
										 |  |  |     })).rejects.toThrow('Failed to load client certificate: mac verify failure'); | 
					
						
							| 
									
										
										
										
											2024-08-05 10:54:33 +02:00
										 |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-29 16:44:53 +02:00
										 |  |  |   test('should pass with matching certificates on context APIRequestContext instance', async ({ browser, startCCServer, asset, browserName }) => { | 
					
						
							| 
									
										
										
										
											2024-09-18 17:09:08 +02:00
										 |  |  |     const serverURL = await startCCServer(); | 
					
						
							| 
									
										
										
										
											2024-07-29 16:44:53 +02:00
										 |  |  |     const baseOptions = { | 
					
						
							|  |  |  |       certPath: asset('client-certificates/client/trusted/cert.pem'), | 
					
						
							|  |  |  |       keyPath: asset('client-certificates/client/trusted/key.pem'), | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     const page = await browser.newPage({ | 
					
						
							| 
									
										
										
										
											2024-09-13 17:34:34 +02:00
										 |  |  |       ignoreHTTPSErrors: true, | 
					
						
							| 
									
										
										
										
											2024-07-29 16:44:53 +02:00
										 |  |  |       clientCertificates: [{ | 
					
						
							|  |  |  |         origin: new URL(serverURL).origin, | 
					
						
							|  |  |  |         ...baseOptions, | 
					
						
							|  |  |  |       }, { | 
					
						
							|  |  |  |         origin: new URL(serverURL).origin.replace('localhost', '127.0.0.1'), | 
					
						
							|  |  |  |         ...baseOptions, | 
					
						
							|  |  |  |       }], | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     for (const url of [serverURL, serverURL.replace('localhost', '127.0.0.1')]) { | 
					
						
							|  |  |  |       const response = await page.request.get(url); | 
					
						
							|  |  |  |       expect(response.status()).toBe(200); | 
					
						
							|  |  |  |       expect(await response.text()).toContain('Hello Alice, your certificate was issued by localhost!'); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     await page.close(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-27 07:06:37 -07:00
										 |  |  |   test('should pass with matching certificates and trailing slash', async ({ browser, startCCServer, asset, browserName, isMac }) => { | 
					
						
							|  |  |  |     const serverURL = await startCCServer({ useFakeLocalhost: browserName === 'webkit' && isMac }); | 
					
						
							| 
									
										
										
										
											2024-07-24 19:13:03 +02:00
										 |  |  |     const page = await browser.newPage({ | 
					
						
							| 
									
										
										
										
											2024-08-02 08:34:28 +02:00
										 |  |  |       ignoreHTTPSErrors: true, | 
					
						
							| 
									
										
										
										
											2024-07-24 19:13:03 +02:00
										 |  |  |       clientCertificates: [{ | 
					
						
							|  |  |  |         origin: serverURL, | 
					
						
							|  |  |  |         certPath: asset('client-certificates/client/trusted/cert.pem'), | 
					
						
							|  |  |  |         keyPath: asset('client-certificates/client/trusted/key.pem'), | 
					
						
							|  |  |  |       }], | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     await page.goto(serverURL); | 
					
						
							|  |  |  |     await expect(page.getByText('Hello Alice, your certificate was issued by localhost!')).toBeVisible(); | 
					
						
							|  |  |  |     await page.close(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-19 12:04:12 +02:00
										 |  |  |   test('should have ignoreHTTPSErrors=false by default', async ({ browser, httpsServer, asset, browserName, platform }) => { | 
					
						
							| 
									
										
										
										
											2024-07-18 22:37:11 +02:00
										 |  |  |     const page = await browser.newPage({ | 
					
						
							|  |  |  |       clientCertificates: [{ | 
					
						
							| 
									
										
										
										
											2024-07-23 22:56:36 +02:00
										 |  |  |         origin: 'https://just-there-that-the-client-certificates-proxy-server-is-getting-launched.com', | 
					
						
							|  |  |  |         certPath: asset('client-certificates/client/trusted/cert.pem'), | 
					
						
							|  |  |  |         keyPath: asset('client-certificates/client/trusted/key.pem'), | 
					
						
							| 
									
										
										
										
											2024-07-18 22:37:11 +02:00
										 |  |  |       }], | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2024-07-19 12:04:12 +02:00
										 |  |  |     await page.goto(browserName === 'webkit' && platform === 'darwin' ? httpsServer.EMPTY_PAGE.replace('localhost', 'local.playwright') : httpsServer.EMPTY_PAGE); | 
					
						
							| 
									
										
										
										
											2024-07-29 14:39:14 +02:00
										 |  |  |     await expect(page.getByText('Playwright client-certificate error: self-signed certificate')).toBeVisible(); | 
					
						
							| 
									
										
										
										
											2024-07-18 22:37:11 +02:00
										 |  |  |     await page.close(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-27 07:06:37 -07:00
										 |  |  |   test('support http2', async ({ browser, startCCServer, asset, browserName, isMac }) => { | 
					
						
							|  |  |  |     test.skip(browserName === 'webkit' && isMac, 'WebKit on macOS doesn\n proxy localhost'); | 
					
						
							| 
									
										
										
										
											2024-08-28 08:23:39 -07:00
										 |  |  |     const serverURL = await startCCServer({ http2: true }); | 
					
						
							| 
									
										
										
										
											2024-07-24 11:39:39 +02:00
										 |  |  |     const page = await browser.newPage({ | 
					
						
							| 
									
										
										
										
											2024-08-02 08:34:28 +02:00
										 |  |  |       ignoreHTTPSErrors: true, | 
					
						
							| 
									
										
										
										
											2024-07-24 11:39:39 +02:00
										 |  |  |       clientCertificates: [{ | 
					
						
							|  |  |  |         origin: new URL(serverURL).origin, | 
					
						
							|  |  |  |         certPath: asset('client-certificates/client/trusted/cert.pem'), | 
					
						
							|  |  |  |         keyPath: asset('client-certificates/client/trusted/key.pem'), | 
					
						
							|  |  |  |       }], | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-09-18 17:09:08 +02:00
										 |  |  |       await page.goto(serverURL.replace('127.0.0.1', 'local.playwright')); | 
					
						
							| 
									
										
										
										
											2024-07-25 18:53:38 +02:00
										 |  |  |       await expect(page.getByTestId('message')).toHaveText('Sorry, but you need to provide a client certificate to continue.'); | 
					
						
							| 
									
										
										
										
											2024-08-28 08:23:39 -07:00
										 |  |  |       await expect(page.getByTestId('alpn-protocol')).toHaveText('h2'); | 
					
						
							| 
									
										
										
										
											2024-07-25 18:53:38 +02:00
										 |  |  |       await expect(page.getByTestId('servername')).toHaveText('local.playwright'); | 
					
						
							| 
									
										
										
										
											2024-07-24 11:39:39 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       await page.goto(serverURL); | 
					
						
							| 
									
										
										
										
											2024-07-25 18:53:38 +02:00
										 |  |  |       await expect(page.getByTestId('message')).toHaveText('Hello Alice, your certificate was issued by localhost!'); | 
					
						
							| 
									
										
										
										
											2024-08-28 08:23:39 -07:00
										 |  |  |       await expect(page.getByTestId('alpn-protocol')).toHaveText('h2'); | 
					
						
							| 
									
										
										
										
											2024-07-24 11:39:39 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     await page.close(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   test('support http2 if the browser only supports http1.1', async ({ browserType, browserName, startCCServer, asset }) => { | 
					
						
							|  |  |  |     test.skip(browserName !== 'chromium'); | 
					
						
							| 
									
										
										
										
											2024-07-26 11:28:45 +02:00
										 |  |  |     const serverURL = await startCCServer({ http2: true, enableHTTP1FallbackWhenUsingHttp2: true }); | 
					
						
							| 
									
										
										
										
											2024-07-24 11:39:39 +02:00
										 |  |  |     const browser = await browserType.launch({ args: ['--disable-http2'] }); | 
					
						
							|  |  |  |     const page = await browser.newPage({ | 
					
						
							| 
									
										
										
										
											2024-08-02 08:34:28 +02:00
										 |  |  |       ignoreHTTPSErrors: true, | 
					
						
							| 
									
										
										
										
											2024-07-24 11:39:39 +02:00
										 |  |  |       clientCertificates: [{ | 
					
						
							|  |  |  |         origin: new URL(serverURL).origin, | 
					
						
							|  |  |  |         certPath: asset('client-certificates/client/trusted/cert.pem'), | 
					
						
							|  |  |  |         keyPath: asset('client-certificates/client/trusted/key.pem'), | 
					
						
							|  |  |  |       }], | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-09-18 17:09:08 +02:00
										 |  |  |       await page.goto(serverURL.replace('127.0.0.1', 'local.playwright')); | 
					
						
							| 
									
										
										
										
											2024-07-25 18:53:38 +02:00
										 |  |  |       await expect(page.getByTestId('message')).toHaveText('Sorry, but you need to provide a client certificate to continue.'); | 
					
						
							|  |  |  |       await expect(page.getByTestId('alpn-protocol')).toHaveText('http/1.1'); | 
					
						
							| 
									
										
										
										
											2024-07-24 11:39:39 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       await page.goto(serverURL); | 
					
						
							| 
									
										
										
										
											2024-07-25 18:53:38 +02:00
										 |  |  |       await expect(page.getByTestId('message')).toHaveText('Hello Alice, your certificate was issued by localhost!'); | 
					
						
							|  |  |  |       await expect(page.getByTestId('alpn-protocol')).toHaveText('http/1.1'); | 
					
						
							| 
									
										
										
										
											2024-07-24 11:39:39 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     await browser.close(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-25 10:33:43 -07:00
										 |  |  |   test('should return target connection errors when using http2', async ({ browser, startCCServer, asset, browserName, isMac, nodeVersion }) => { | 
					
						
							| 
									
										
										
										
											2024-10-04 08:22:27 -07:00
										 |  |  |     test.skip(browserName === 'webkit' && isMac, 'WebKit on macOS does not proxy localhost'); | 
					
						
							| 
									
										
										
										
											2024-10-25 10:33:43 -07:00
										 |  |  |     test.skip(nodeVersion.major < 20, 'http2.performServerHandshake is not supported in older Node.js versions'); | 
					
						
							| 
									
										
										
										
											2024-07-26 11:28:45 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const serverURL = await startCCServer({ http2: true }); | 
					
						
							|  |  |  |     const page = await browser.newPage({ | 
					
						
							|  |  |  |       clientCertificates: [{ | 
					
						
							|  |  |  |         origin: 'https://just-there-that-the-client-certificates-proxy-server-is-getting-launched.com', | 
					
						
							|  |  |  |         certPath: asset('client-certificates/client/trusted/cert.pem'), | 
					
						
							|  |  |  |         keyPath: asset('client-certificates/client/trusted/key.pem'), | 
					
						
							|  |  |  |       }], | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     await page.goto(serverURL); | 
					
						
							|  |  |  |     await expect(page.getByText('Playwright client-certificate error: self-signed certificate')).toBeVisible(); | 
					
						
							|  |  |  |     await page.close(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-22 15:13:54 +02:00
										 |  |  |   test('should handle rejected certificate in handshake with HTTP/2', async ({ browser, asset, browserName, platform }) => { | 
					
						
							|  |  |  |     const server: http2.Http2SecureServer = createHttp2Server({ | 
					
						
							|  |  |  |       key: fs.readFileSync(asset('client-certificates/server/server_key.pem')), | 
					
						
							|  |  |  |       cert: fs.readFileSync(asset('client-certificates/server/server_cert.pem')), | 
					
						
							|  |  |  |       ca: [fs.readFileSync(asset('client-certificates/server/server_cert.pem'))], | 
					
						
							|  |  |  |       requestCert: true, | 
					
						
							|  |  |  |     }, async (req: http2.Http2ServerRequest, res: http2.Http2ServerResponse) => { | 
					
						
							|  |  |  |       res.writeHead(200, { 'Content-Type': 'text/html' }); | 
					
						
							|  |  |  |       res.end('Hello world'); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     await new Promise<void>(resolve => server.listen(0, 'localhost', resolve)); | 
					
						
							|  |  |  |     const port = (server.address() as net.AddressInfo).port; | 
					
						
							|  |  |  |     const serverUrl = 'https://' + (browserName === 'webkit' && platform === 'darwin' ? 'local.playwright' : 'localhost') + ':' + port; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const context = await browser.newContext({ | 
					
						
							|  |  |  |       ignoreHTTPSErrors: true, | 
					
						
							|  |  |  |       clientCertificates: [{ | 
					
						
							|  |  |  |         origin: 'https://just-there-that-the-client-certificates-proxy-server-is-getting-launched.com', | 
					
						
							|  |  |  |         certPath: asset('client-certificates/client/trusted/cert.pem'), | 
					
						
							|  |  |  |         keyPath: asset('client-certificates/client/trusted/key.pem'), | 
					
						
							|  |  |  |       }], | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const page = await context.newPage(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // This was triggering an unhandled error before.
 | 
					
						
							|  |  |  |     await page.goto(serverUrl).catch(() => {}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     await context.close(); | 
					
						
							|  |  |  |     await new Promise<void>(resolve => server.close(() => resolve())); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |   test.describe('persistentContext', () => { | 
					
						
							|  |  |  |     test('validate input', async ({ launchPersistent }) => { | 
					
						
							|  |  |  |       test.slow(); | 
					
						
							|  |  |  |       for (const [contextOptions, expected] of kValidationSubTests) | 
					
						
							|  |  |  |         await expect(launchPersistent(contextOptions)).rejects.toThrow(expected); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-27 07:06:37 -07:00
										 |  |  |     test('should pass with matching certificates', async ({ launchPersistent, startCCServer, asset, browserName, isMac }) => { | 
					
						
							|  |  |  |       const serverURL = await startCCServer({ useFakeLocalhost: browserName === 'webkit' && isMac }); | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |       const { page } = await launchPersistent({ | 
					
						
							| 
									
										
										
										
											2024-08-02 08:34:28 +02:00
										 |  |  |         ignoreHTTPSErrors: true, | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |         clientCertificates: [{ | 
					
						
							| 
									
										
										
										
											2024-07-23 22:56:36 +02:00
										 |  |  |           origin: new URL(serverURL).origin, | 
					
						
							|  |  |  |           certPath: asset('client-certificates/client/trusted/cert.pem'), | 
					
						
							|  |  |  |           keyPath: asset('client-certificates/client/trusted/key.pem'), | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |         }], | 
					
						
							|  |  |  |       }); | 
					
						
							| 
									
										
										
										
											2024-07-23 19:18:31 +02:00
										 |  |  |       await page.goto(serverURL); | 
					
						
							| 
									
										
										
										
											2024-07-25 18:53:38 +02:00
										 |  |  |       await expect(page.getByTestId('message')).toHaveText('Hello Alice, your certificate was issued by localhost!'); | 
					
						
							| 
									
										
										
										
											2024-07-12 11:42:24 +02:00
										 |  |  |     }); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | }); |