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-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-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 ? : {
2024-07-29 16:44:53 +02:00
host? : string ;
2024-07-23 19:18:31 +02:00
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-07-29 16:44:53 +02:00
await new Promise < void > ( f = > server . listen ( 0 , options ? . host ? ? 'localhost' , ( ) = > f ( ) ) ) ;
2024-07-23 19:18:31 +02:00
const host = options ? . useFakeLocalhost ? 'local.playwright' : 'localhost' ;
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
} ,
} ) ;
2024-07-18 13:43:56 +02:00
test . use ( {
launchOptions : async ( { launchOptions } , use ) = > {
await use ( {
. . . launchOptions ,
proxy : { server : 'per-context' }
} ) ;
}
} ) ;
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' ] ,
[ {
proxy : { server : 'http://localhost:8080' } ,
clientCertificates : [ {
2024-07-23 22:56:36 +02:00
origin : 'test' ,
certPath : kDummyFileName ,
keyPath : kDummyFileName ,
2024-07-12 11:42:24 +02:00
} ]
} , 'Cannot specify both proxy and clientCertificates' ] ,
] ;
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-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-07-23 19:18:31 +02:00
test ( 'should fail with no client certificates' , async ( { browser , startCCServer , asset , browserName } ) = > {
const serverURL = await startCCServer ( { useFakeLocalhost : browserName === 'webkit' && process . platform === 'darwin' } ) ;
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-07-23 19:18:31 +02:00
test ( 'should fail with self-signed client certificates' , async ( { browser , startCCServer , asset , browserName } ) = > {
const serverURL = await startCCServer ( { useFakeLocalhost : browserName === 'webkit' && process . platform === 'darwin' } ) ;
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-07-23 19:18:31 +02:00
test ( 'should pass with matching certificates' , async ( { browser , startCCServer , asset , browserName } ) = > {
const serverURL = await startCCServer ( { useFakeLocalhost : browserName === 'webkit' && process . platform === 'darwin' } ) ;
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-07-29 16:44:53 +02:00
test ( 'should pass with matching certificates on context APIRequestContext instance' , async ( { browser , startCCServer , asset , browserName } ) = > {
const serverURL = await startCCServer ( { host : '127.0.0.1' } ) ;
const baseOptions = {
certPath : asset ( 'client-certificates/client/trusted/cert.pem' ) ,
keyPath : asset ( 'client-certificates/client/trusted/key.pem' ) ,
} ;
const page = await browser . newPage ( {
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-07-24 19:13:03 +02:00
test ( 'should pass with matching certificates and trailing slash' , async ( { browser , startCCServer , asset , browserName } ) = > {
const serverURL = await startCCServer ( { useFakeLocalhost : browserName === 'webkit' && process . platform === 'darwin' } ) ;
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-07-24 11:39:39 +02:00
test ( 'support http2' , async ( { browser , startCCServer , asset , browserName } ) = > {
test . skip ( browserName === 'webkit' && process . platform === 'darwin' , 'WebKit on macOS doesn\n proxy localhost' ) ;
2024-07-26 11:28:45 +02:00
const enableHTTP1FallbackWhenUsingHttp2 = browserName === 'webkit' && process . platform === 'linux' ;
const serverURL = await startCCServer ( { http2 : true , enableHTTP1FallbackWhenUsingHttp2 } ) ;
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' ) ,
} ] ,
} ) ;
// TODO: We should investigate why http2 is not supported in WebKit on Linux.
// https://bugs.webkit.org/show_bug.cgi?id=276990
2024-07-26 11:28:45 +02:00
const expectedProtocol = enableHTTP1FallbackWhenUsingHttp2 ? 'http/1.1' : 'h2' ;
2024-07-24 11:39:39 +02:00
{
await page . goto ( serverURL . replace ( 'localhost' , '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 ( expectedProtocol ) ;
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!' ) ;
await expect ( page . getByTestId ( 'alpn-protocol' ) ) . toHaveText ( expectedProtocol ) ;
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' ) ,
} ] ,
} ) ;
{
await page . goto ( serverURL . replace ( 'localhost' , '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-07-26 11:28:45 +02:00
test ( 'should return target connection errors when using http2' , async ( { browser , startCCServer , asset , browserName } ) = > {
test . skip ( browserName === 'webkit' && process . platform === 'darwin' , 'WebKit on macOS doesn\n proxy localhost' ) ;
test . fixme ( browserName === 'webkit' && process . platform === 'linux' , 'WebKit on Linux does not support http2 https://bugs.webkit.org/show_bug.cgi?id=276990' ) ;
test . skip ( + process . versions . node . split ( '.' ) [ 0 ] < 20 , 'http2.performServerHandshake is not supported in older Node.js versions' ) ;
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-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-07-23 19:18:31 +02:00
test ( 'should pass with matching certificates' , async ( { launchPersistent , startCCServer , asset , browserName } ) = > {
const serverURL = await startCCServer ( { useFakeLocalhost : browserName === 'webkit' && process . platform === 'darwin' } ) ;
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
} ) ;
} ) ;
} ) ;