From b256d3c2bc99356b41531b83d84ec42b2402da2d Mon Sep 17 00:00:00 2001 From: shibaofeng Date: Sat, 29 Sep 2018 20:42:45 +0800 Subject: [PATCH] feat: support to fill popup auth dialog #457 --- docs/api.md | 20 +++++++++++++++++ src/api.ts | 11 ++++++++++ src/chrome/local-runtime.ts | 43 +++++++++++++++++++++++++++++++++++++ src/types.ts | 12 +++++++++++ 4 files changed, 86 insertions(+) diff --git a/docs/api.md b/docs/api.md index f961e5d4..6542e5eb 100644 --- a/docs/api.md +++ b/docs/api.md @@ -53,6 +53,7 @@ Chromeless provides TypeScript typings. - [`setCookies(cookie: Cookie)`](#api-setcookies-one) - [`setCookies(cookies: Cookie[])`](#api-setcookies-many) - [`deleteCookies(name: string)`](#api-deletecookies) +- [`authenticate(username: string, password: string, patterns?: RequestPattern[])`](#api-authenticate) - [`clearCookies()`](#api-clearcookies) @@ -770,3 +771,22 @@ __Example__ ```js await chromeless.setFileInput('.uploader', '/User/Me/Documents/img.jpg') ``` +--------------------------------------- + + + +### authenticate(username: string, password: string, patterns?: RequestPattern[]): Chromeless + +provide authenticate for pop up dialog + +RequestPattern is defined as [here](https://chromedevtools.github.io/devtools-protocol/tot/Network#type-RequestPattern) + + +__Example__ + +```js +await chromeless + .authenticate('username', 'Passw0Rd',[{urlPattern: '*'}]) + .goto('https://github.com') + .screenshot() +``` diff --git a/src/api.ts b/src/api.ts index cb05faa2..6fd535d3 100644 --- a/src/api.ts +++ b/src/api.ts @@ -9,6 +9,7 @@ import { PdfOptions, DeviceMetrics, ScreenshotOptions, + RequestPattern, } from './types' import { getDebugOption } from './util' import { isArray } from 'util' @@ -198,6 +199,16 @@ export default class Chromeless implements Promise { return this } + authenticate( + username: string, + password: string, + patterns?: RequestPattern[], + ): Chromeless { + this.queue.enqueue({ type: 'authenticate', username, password, patterns }) + + return this + } + setExtraHTTPHeaders(headers: Headers): Chromeless { this.queue.enqueue({ type: 'setExtraHTTPHeaders', headers }) diff --git a/src/chrome/local-runtime.ts b/src/chrome/local-runtime.ts index b376cf1c..56701b56 100644 --- a/src/chrome/local-runtime.ts +++ b/src/chrome/local-runtime.ts @@ -7,6 +7,7 @@ import { CookieQuery, PdfOptions, ScreenshotOptions, + RequestPattern, } from '../types' import { nodeExists, @@ -123,6 +124,12 @@ export default class LocalRuntime { return this.clearInput(command.selector) case 'setFileInput': return this.setFileInput(command.selector, command.files) + case 'authenticate': + return this.authenticate( + command.username, + command.password, + command.patterns, + ) default: throw new Error(`No such command: ${JSON.stringify(command)}`) } @@ -173,6 +180,42 @@ export default class LocalRuntime { await this.log(`Set useragent to ${this.userAgentValue}`) } + private async authenticate( + username: string, + password: string, + pattens?: RequestPattern[], + ): Promise { + const { Network } = this.client + await Network.setRequestInterception({ + patterns: pattens ? pattens : [{ urlPattern: '*' }], + }) + + Network.requestIntercepted( + async ({ interceptionId, request, authChallenge }) => { + // perform a test against the intercepted request + this.log( + `${interceptionId} ${request.url} ${ + authChallenge ? authChallenge.origin : 'undefined' + } ${authChallenge ? authChallenge.scheme : 'undefined'}`, + ) + if (authChallenge) { + await Network.continueInterceptedRequest({ + interceptionId: interceptionId, + authChallengeResponse: { + response: 'ProvideCredentials', + username: username, + password: password, + }, + }) + } else { + await Network.continueInterceptedRequest({ + interceptionId: interceptionId, + }) + } + }, + ) + } + private async waitTimeout(timeout: number): Promise { this.log(`Waiting for ${timeout}ms`) await wait(timeout) diff --git a/src/types.ts b/src/types.ts index 4d50687c..15370f24 100644 --- a/src/types.ts +++ b/src/types.ts @@ -196,6 +196,12 @@ export type Command = selector: string files: string[] } + | { + type: 'authenticate' + username: string + password: string + patterns?: RequestPattern[] + } export type Headers = Record @@ -269,3 +275,9 @@ export interface Viewport { height: number scale: number } + +export interface RequestPattern { + urlPattern?: string + resourceType?: string + interceptionStage?: string +}