feat(expext): toBeOK for APIResponse (#10596)
This commit is contained in:
parent
729da65eba
commit
d66b7aab3b
|
|
@ -268,6 +268,11 @@ export class APIResponse implements api.APIResponse {
|
||||||
_fetchUid(): string {
|
_fetchUid(): string {
|
||||||
return this._initializer.fetchUid;
|
return this._initializer.fetchUid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _fetchLog(): Promise<string[]> {
|
||||||
|
const { log } = await this._request._channel.fetchLog({ fetchUid: this._fetchUid() });
|
||||||
|
return log;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServerFilePayload = NonNullable<channels.FormField['file']>;
|
type ServerFilePayload = NonNullable<channels.FormField['file']>;
|
||||||
|
|
|
||||||
|
|
@ -178,8 +178,8 @@ export class APIRequestContextDispatcher extends Dispatcher<APIRequestContext, c
|
||||||
this._object.dispose();
|
this._object.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetch(params: channels.APIRequestContextFetchParams, metadata?: channels.Metadata): Promise<channels.APIRequestContextFetchResult> {
|
async fetch(params: channels.APIRequestContextFetchParams, metadata: CallMetadata): Promise<channels.APIRequestContextFetchResult> {
|
||||||
const fetchResponse = await this._object.fetch(params);
|
const fetchResponse = await this._object.fetch(params, metadata);
|
||||||
return {
|
return {
|
||||||
response: {
|
response: {
|
||||||
url: fetchResponse.url,
|
url: fetchResponse.url,
|
||||||
|
|
@ -196,7 +196,12 @@ export class APIRequestContextDispatcher extends Dispatcher<APIRequestContext, c
|
||||||
return { binary: buffer ? buffer.toString('base64') : undefined };
|
return { binary: buffer ? buffer.toString('base64') : undefined };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fetchLog(params: channels.APIRequestContextFetchLogParams, metadata?: channels.Metadata): Promise<channels.APIRequestContextFetchLogResult> {
|
||||||
|
const log = this._object.fetchLog.get(params.fetchUid) || [];
|
||||||
|
return { log };
|
||||||
|
}
|
||||||
|
|
||||||
async disposeAPIResponse(params: channels.APIRequestContextDisposeAPIResponseParams, metadata?: channels.Metadata): Promise<void> {
|
async disposeAPIResponse(params: channels.APIRequestContextDisposeAPIResponseParams, metadata?: channels.Metadata): Promise<void> {
|
||||||
this._object.fetchResponses.delete(params.fetchUid);
|
this._object.disposeResponse(params.fetchUid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -266,6 +266,7 @@ export interface APIRequestContextChannel extends APIRequestContextEventTarget,
|
||||||
_type_APIRequestContext: boolean;
|
_type_APIRequestContext: boolean;
|
||||||
fetch(params: APIRequestContextFetchParams, metadata?: Metadata): Promise<APIRequestContextFetchResult>;
|
fetch(params: APIRequestContextFetchParams, metadata?: Metadata): Promise<APIRequestContextFetchResult>;
|
||||||
fetchResponseBody(params: APIRequestContextFetchResponseBodyParams, metadata?: Metadata): Promise<APIRequestContextFetchResponseBodyResult>;
|
fetchResponseBody(params: APIRequestContextFetchResponseBodyParams, metadata?: Metadata): Promise<APIRequestContextFetchResponseBodyResult>;
|
||||||
|
fetchLog(params: APIRequestContextFetchLogParams, metadata?: Metadata): Promise<APIRequestContextFetchLogResult>;
|
||||||
storageState(params?: APIRequestContextStorageStateParams, metadata?: Metadata): Promise<APIRequestContextStorageStateResult>;
|
storageState(params?: APIRequestContextStorageStateParams, metadata?: Metadata): Promise<APIRequestContextStorageStateResult>;
|
||||||
disposeAPIResponse(params: APIRequestContextDisposeAPIResponseParams, metadata?: Metadata): Promise<APIRequestContextDisposeAPIResponseResult>;
|
disposeAPIResponse(params: APIRequestContextDisposeAPIResponseParams, metadata?: Metadata): Promise<APIRequestContextDisposeAPIResponseResult>;
|
||||||
dispose(params?: APIRequestContextDisposeParams, metadata?: Metadata): Promise<APIRequestContextDisposeResult>;
|
dispose(params?: APIRequestContextDisposeParams, metadata?: Metadata): Promise<APIRequestContextDisposeResult>;
|
||||||
|
|
@ -307,6 +308,15 @@ export type APIRequestContextFetchResponseBodyOptions = {
|
||||||
export type APIRequestContextFetchResponseBodyResult = {
|
export type APIRequestContextFetchResponseBodyResult = {
|
||||||
binary?: Binary,
|
binary?: Binary,
|
||||||
};
|
};
|
||||||
|
export type APIRequestContextFetchLogParams = {
|
||||||
|
fetchUid: string,
|
||||||
|
};
|
||||||
|
export type APIRequestContextFetchLogOptions = {
|
||||||
|
|
||||||
|
};
|
||||||
|
export type APIRequestContextFetchLogResult = {
|
||||||
|
log: string[],
|
||||||
|
};
|
||||||
export type APIRequestContextStorageStateParams = {};
|
export type APIRequestContextStorageStateParams = {};
|
||||||
export type APIRequestContextStorageStateOptions = {};
|
export type APIRequestContextStorageStateOptions = {};
|
||||||
export type APIRequestContextStorageStateResult = {
|
export type APIRequestContextStorageStateResult = {
|
||||||
|
|
|
||||||
|
|
@ -262,6 +262,14 @@ APIRequestContext:
|
||||||
returns:
|
returns:
|
||||||
binary?: binary
|
binary?: binary
|
||||||
|
|
||||||
|
fetchLog:
|
||||||
|
parameters:
|
||||||
|
fetchUid: string
|
||||||
|
returns:
|
||||||
|
log:
|
||||||
|
type: array
|
||||||
|
items: string
|
||||||
|
|
||||||
storageState:
|
storageState:
|
||||||
returns:
|
returns:
|
||||||
cookies:
|
cookies:
|
||||||
|
|
|
||||||
|
|
@ -173,6 +173,9 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
|
||||||
scheme.APIRequestContextFetchResponseBodyParams = tObject({
|
scheme.APIRequestContextFetchResponseBodyParams = tObject({
|
||||||
fetchUid: tString,
|
fetchUid: tString,
|
||||||
});
|
});
|
||||||
|
scheme.APIRequestContextFetchLogParams = tObject({
|
||||||
|
fetchUid: tString,
|
||||||
|
});
|
||||||
scheme.APIRequestContextStorageStateParams = tOptional(tObject({}));
|
scheme.APIRequestContextStorageStateParams = tOptional(tObject({}));
|
||||||
scheme.APIRequestContextDisposeAPIResponseParams = tObject({
|
scheme.APIRequestContextDisposeAPIResponseParams = tObject({
|
||||||
fetchUid: tString,
|
fetchUid: tString,
|
||||||
|
|
|
||||||
|
|
@ -17,19 +17,19 @@
|
||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
import * as https from 'https';
|
import * as https from 'https';
|
||||||
import { HttpsProxyAgent } from 'https-proxy-agent';
|
import { HttpsProxyAgent } from 'https-proxy-agent';
|
||||||
|
import { Progress, ProgressController } from './progress';
|
||||||
import { SocksProxyAgent } from 'socks-proxy-agent';
|
import { SocksProxyAgent } from 'socks-proxy-agent';
|
||||||
import { pipeline, Readable, Transform } from 'stream';
|
import { pipeline, Readable, Transform } from 'stream';
|
||||||
import url from 'url';
|
import url from 'url';
|
||||||
import zlib from 'zlib';
|
import zlib from 'zlib';
|
||||||
import { HTTPCredentials } from '../../types/types';
|
import { HTTPCredentials } from '../../types/types';
|
||||||
import * as channels from '../protocol/channels';
|
import * as channels from '../protocol/channels';
|
||||||
import { debugLogger } from '../utils/debugLogger';
|
|
||||||
import { TimeoutSettings } from '../utils/timeoutSettings';
|
import { TimeoutSettings } from '../utils/timeoutSettings';
|
||||||
import { assert, createGuid, getPlaywrightVersion, monotonicTime } from '../utils/utils';
|
import { assert, createGuid, getPlaywrightVersion, monotonicTime } from '../utils/utils';
|
||||||
import { BrowserContext } from './browserContext';
|
import { BrowserContext } from './browserContext';
|
||||||
import { CookieStore, domainMatches } from './cookieStore';
|
import { CookieStore, domainMatches } from './cookieStore';
|
||||||
import { MultipartFormData } from './formData';
|
import { MultipartFormData } from './formData';
|
||||||
import { SdkObject } from './instrumentation';
|
import { CallMetadata, SdkObject } from './instrumentation';
|
||||||
import { Playwright } from './playwright';
|
import { Playwright } from './playwright';
|
||||||
import * as types from './types';
|
import * as types from './types';
|
||||||
import { HeadersArray, ProxySettings } from './types';
|
import { HeadersArray, ProxySettings } from './types';
|
||||||
|
|
@ -50,6 +50,7 @@ export abstract class APIRequestContext extends SdkObject {
|
||||||
};
|
};
|
||||||
|
|
||||||
readonly fetchResponses: Map<string, Buffer> = new Map();
|
readonly fetchResponses: Map<string, Buffer> = new Map();
|
||||||
|
readonly fetchLog: Map<string, string[]> = new Map();
|
||||||
protected static allInstances: Set<APIRequestContext> = new Set();
|
protected static allInstances: Set<APIRequestContext> = new Set();
|
||||||
|
|
||||||
static findResponseBody(guid: string): Buffer | undefined {
|
static findResponseBody(guid: string): Buffer | undefined {
|
||||||
|
|
@ -69,9 +70,15 @@ export abstract class APIRequestContext extends SdkObject {
|
||||||
protected _disposeImpl() {
|
protected _disposeImpl() {
|
||||||
APIRequestContext.allInstances.delete(this);
|
APIRequestContext.allInstances.delete(this);
|
||||||
this.fetchResponses.clear();
|
this.fetchResponses.clear();
|
||||||
|
this.fetchLog.clear();
|
||||||
this.emit(APIRequestContext.Events.Dispose);
|
this.emit(APIRequestContext.Events.Dispose);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
disposeResponse(fetchUid: string) {
|
||||||
|
this.fetchResponses.delete(fetchUid);
|
||||||
|
this.fetchLog.delete(fetchUid);
|
||||||
|
}
|
||||||
|
|
||||||
abstract dispose(): void;
|
abstract dispose(): void;
|
||||||
|
|
||||||
abstract _defaultOptions(): FetchRequestOptions;
|
abstract _defaultOptions(): FetchRequestOptions;
|
||||||
|
|
@ -85,7 +92,7 @@ export abstract class APIRequestContext extends SdkObject {
|
||||||
return uid;
|
return uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetch(params: channels.APIRequestContextFetchParams): Promise<Omit<types.APIResponse, 'body'> & { fetchUid: string }> {
|
async fetch(params: channels.APIRequestContextFetchParams, metadata: CallMetadata): Promise<Omit<types.APIResponse, 'body'> & { fetchUid: string }> {
|
||||||
const headers: { [name: string]: string } = {};
|
const headers: { [name: string]: string } = {};
|
||||||
const defaults = this._defaultOptions();
|
const defaults = this._defaultOptions();
|
||||||
headers['user-agent'] = defaults.userAgent;
|
headers['user-agent'] = defaults.userAgent;
|
||||||
|
|
@ -141,15 +148,19 @@ export abstract class APIRequestContext extends SdkObject {
|
||||||
requestUrl.searchParams.set(name, value);
|
requestUrl.searchParams.set(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
let postData;
|
let postData: Buffer | undefined;
|
||||||
if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(method))
|
if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(method))
|
||||||
postData = serializePostData(params, headers);
|
postData = serializePostData(params, headers);
|
||||||
else if (params.postData || params.jsonData || params.formData || params.multipartData)
|
else if (params.postData || params.jsonData || params.formData || params.multipartData)
|
||||||
throw new Error(`Method ${method} does not accept post data`);
|
throw new Error(`Method ${method} does not accept post data`);
|
||||||
if (postData)
|
if (postData)
|
||||||
headers['content-length'] = String(postData.byteLength);
|
headers['content-length'] = String(postData.byteLength);
|
||||||
const fetchResponse = await this._sendRequest(requestUrl, options, postData);
|
const controller = new ProgressController(metadata, this);
|
||||||
|
const fetchResponse = await controller.run(progress => {
|
||||||
|
return this._sendRequest(progress, requestUrl, options, postData);
|
||||||
|
});
|
||||||
const fetchUid = this._storeResponseBody(fetchResponse.body);
|
const fetchUid = this._storeResponseBody(fetchResponse.body);
|
||||||
|
this.fetchLog.set(fetchUid, controller.metadata.log);
|
||||||
if (params.failOnStatusCode && (fetchResponse.status < 200 || fetchResponse.status >= 400))
|
if (params.failOnStatusCode && (fetchResponse.status < 200 || fetchResponse.status >= 400))
|
||||||
throw new Error(`${fetchResponse.status} ${fetchResponse.statusText}`);
|
throw new Error(`${fetchResponse.status} ${fetchResponse.statusText}`);
|
||||||
return { ...fetchResponse, fetchUid };
|
return { ...fetchResponse, fetchUid };
|
||||||
|
|
@ -191,17 +202,15 @@ export abstract class APIRequestContext extends SdkObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _sendRequest(url: URL, options: https.RequestOptions & { maxRedirects: number, deadline: number }, postData?: Buffer): Promise<types.APIResponse>{
|
private async _sendRequest(progress: Progress, url: URL, options: https.RequestOptions & { maxRedirects: number, deadline: number }, postData?: Buffer): Promise<types.APIResponse>{
|
||||||
await this._updateRequestCookieHeader(url, options);
|
await this._updateRequestCookieHeader(url, options);
|
||||||
return new Promise<types.APIResponse>((fulfill, reject) => {
|
return new Promise<types.APIResponse>((fulfill, reject) => {
|
||||||
const requestConstructor: ((url: URL, options: http.RequestOptions, callback?: (res: http.IncomingMessage) => void) => http.ClientRequest)
|
const requestConstructor: ((url: URL, options: http.RequestOptions, callback?: (res: http.IncomingMessage) => void) => http.ClientRequest)
|
||||||
= (url.protocol === 'https:' ? https : http).request;
|
= (url.protocol === 'https:' ? https : http).request;
|
||||||
const request = requestConstructor(url, options, async response => {
|
const request = requestConstructor(url, options, async response => {
|
||||||
if (debugLogger.isEnabled('api')) {
|
progress.log(`← ${response.statusCode} ${response.statusMessage}`);
|
||||||
debugLogger.log('api', `← ${response.statusCode} ${response.statusMessage}`);
|
for (const [name, value] of Object.entries(response.headers))
|
||||||
for (const [name, value] of Object.entries(response.headers))
|
progress.log(` ${name}: ${value}`);
|
||||||
debugLogger.log('api', ` ${name}: ${value}`);
|
|
||||||
}
|
|
||||||
if (response.headers['set-cookie'])
|
if (response.headers['set-cookie'])
|
||||||
await this._updateCookiesFromHeader(response.url || url.toString(), response.headers['set-cookie']);
|
await this._updateCookiesFromHeader(response.url || url.toString(), response.headers['set-cookie']);
|
||||||
if (redirectStatus.includes(response.statusCode!)) {
|
if (redirectStatus.includes(response.statusCode!)) {
|
||||||
|
|
@ -242,7 +251,7 @@ export abstract class APIRequestContext extends SdkObject {
|
||||||
// HTTP-redirect fetch step 4: If locationURL is null, then return response.
|
// HTTP-redirect fetch step 4: If locationURL is null, then return response.
|
||||||
if (response.headers.location) {
|
if (response.headers.location) {
|
||||||
const locationURL = new URL(response.headers.location, url);
|
const locationURL = new URL(response.headers.location, url);
|
||||||
fulfill(this._sendRequest(locationURL, redirectOptions, postData));
|
fulfill(this._sendRequest(progress, locationURL, redirectOptions, postData));
|
||||||
request.destroy();
|
request.destroy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -254,7 +263,7 @@ export abstract class APIRequestContext extends SdkObject {
|
||||||
const { username, password } = credentials;
|
const { username, password } = credentials;
|
||||||
const encoded = Buffer.from(`${username || ''}:${password || ''}`).toString('base64');
|
const encoded = Buffer.from(`${username || ''}:${password || ''}`).toString('base64');
|
||||||
options.headers!['authorization'] = `Basic ${encoded}`;
|
options.headers!['authorization'] = `Basic ${encoded}`;
|
||||||
fulfill(this._sendRequest(url, options, postData));
|
fulfill(this._sendRequest(progress, url, options, postData));
|
||||||
request.destroy();
|
request.destroy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -304,12 +313,10 @@ export abstract class APIRequestContext extends SdkObject {
|
||||||
this.on(APIRequestContext.Events.Dispose, disposeListener);
|
this.on(APIRequestContext.Events.Dispose, disposeListener);
|
||||||
request.on('close', () => this.off(APIRequestContext.Events.Dispose, disposeListener));
|
request.on('close', () => this.off(APIRequestContext.Events.Dispose, disposeListener));
|
||||||
|
|
||||||
if (debugLogger.isEnabled('api')) {
|
progress.log(`→ ${options.method} ${url.toString()}`);
|
||||||
debugLogger.log('api', `→ ${options.method} ${url.toString()}`);
|
if (options.headers) {
|
||||||
if (options.headers) {
|
for (const [name, value] of Object.entries(options.headers))
|
||||||
for (const [name, value] of Object.entries(options.headers))
|
progress.log(` ${name}: ${value}`);
|
||||||
debugLogger.log('api', ` ${name}: ${value}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.deadline) {
|
if (options.deadline) {
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import {
|
||||||
toBeEnabled,
|
toBeEnabled,
|
||||||
toBeFocused,
|
toBeFocused,
|
||||||
toBeHidden,
|
toBeHidden,
|
||||||
|
toBeOK,
|
||||||
toBeVisible,
|
toBeVisible,
|
||||||
toContainText,
|
toContainText,
|
||||||
toHaveAttribute,
|
toHaveAttribute,
|
||||||
|
|
@ -101,6 +102,7 @@ const customMatchers = {
|
||||||
toBeEnabled,
|
toBeEnabled,
|
||||||
toBeFocused,
|
toBeFocused,
|
||||||
toBeHidden,
|
toBeHidden,
|
||||||
|
toBeOK,
|
||||||
toBeVisible,
|
toBeVisible,
|
||||||
toContainText,
|
toContainText,
|
||||||
toHaveAttribute,
|
toHaveAttribute,
|
||||||
|
|
|
||||||
|
|
@ -14,18 +14,23 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Locator, Page } from 'playwright-core';
|
import { Locator, Page, APIResponse } from 'playwright-core';
|
||||||
import { FrameExpectOptions } from 'playwright-core/lib/client/types';
|
import { FrameExpectOptions } from 'playwright-core/lib/client/types';
|
||||||
import { constructURLBasedOnBaseURL } from 'playwright-core/lib/utils/utils';
|
import { constructURLBasedOnBaseURL } from 'playwright-core/lib/utils/utils';
|
||||||
import type { Expect } from '../types';
|
import type { Expect } from '../types';
|
||||||
|
import { expectType } from '../util';
|
||||||
import { toBeTruthy } from './toBeTruthy';
|
import { toBeTruthy } from './toBeTruthy';
|
||||||
import { toEqual } from './toEqual';
|
import { toEqual } from './toEqual';
|
||||||
import { toExpectedTextValues, toMatchText } from './toMatchText';
|
import { callLogText, toExpectedTextValues, toMatchText } from './toMatchText';
|
||||||
|
|
||||||
interface LocatorEx extends Locator {
|
interface LocatorEx extends Locator {
|
||||||
_expect(expression: string, options: FrameExpectOptions): Promise<{ matches: boolean, received?: any, log?: string[] }>;
|
_expect(expression: string, options: FrameExpectOptions): Promise<{ matches: boolean, received?: any, log?: string[] }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface APIResponseEx extends APIResponse {
|
||||||
|
_fetchLog(): Promise<string[]>;
|
||||||
|
}
|
||||||
|
|
||||||
export function toBeChecked(
|
export function toBeChecked(
|
||||||
this: ReturnType<Expect['getState']>,
|
this: ReturnType<Expect['getState']>,
|
||||||
locator: LocatorEx,
|
locator: LocatorEx,
|
||||||
|
|
@ -263,3 +268,15 @@ export function toHaveURL(
|
||||||
return await locator._expect('to.have.url', { expectedText, isNot, timeout });
|
return await locator._expect('to.have.url', { expectedText, isNot, timeout });
|
||||||
}, expected, options);
|
}, expected, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function toBeOK(
|
||||||
|
this: ReturnType<Expect['getState']>,
|
||||||
|
response: APIResponseEx
|
||||||
|
) {
|
||||||
|
const matcherName = 'toBeOK';
|
||||||
|
expectType(response, 'APIResponse', matcherName);
|
||||||
|
const log = (this.isNot === response.ok()) ? await response._fetchLog() : [];
|
||||||
|
const message = () => this.utils.matcherHint(matcherName, undefined, '', { isNot: this.isNot }) + callLogText(log);
|
||||||
|
const pass = response.ok();
|
||||||
|
return { message, pass };
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,11 @@ declare global {
|
||||||
*/
|
*/
|
||||||
toBeHidden(options?: { timeout?: number }): Promise<R>;
|
toBeHidden(options?: { timeout?: number }): Promise<R>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts given APIResponse's status is between 200 and 299.
|
||||||
|
*/
|
||||||
|
toBeOK(): Promise<R>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asserts given DOM node visible on the screen.
|
* Asserts given DOM node visible on the screen.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ it('should throw on network error', async ({ context, server }) => {
|
||||||
req.socket.destroy();
|
req.socket.destroy();
|
||||||
});
|
});
|
||||||
const error = await context.request.get(server.PREFIX + '/test').catch(e => e);
|
const error = await context.request.get(server.PREFIX + '/test').catch(e => e);
|
||||||
expect(error.message).toBe('apiRequestContext.get: socket hang up');
|
expect(error.message).toContain('apiRequestContext.get: socket hang up');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw on network error after redirect', async ({ context, server }) => {
|
it('should throw on network error after redirect', async ({ context, server }) => {
|
||||||
|
|
@ -78,7 +78,7 @@ it('should throw on network error after redirect', async ({ context, server }) =
|
||||||
req.socket.destroy();
|
req.socket.destroy();
|
||||||
});
|
});
|
||||||
const error = await context.request.get(server.PREFIX + '/redirect').catch(e => e);
|
const error = await context.request.get(server.PREFIX + '/redirect').catch(e => e);
|
||||||
expect(error.message).toBe('apiRequestContext.get: socket hang up');
|
expect(error.message).toContain('apiRequestContext.get: socket hang up');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw on network error when sending body', async ({ context, server }) => {
|
it('should throw on network error when sending body', async ({ context, server }) => {
|
||||||
|
|
@ -92,7 +92,7 @@ it('should throw on network error when sending body', async ({ context, server }
|
||||||
req.socket.destroy();
|
req.socket.destroy();
|
||||||
});
|
});
|
||||||
const error = await context.request.get(server.PREFIX + '/test').catch(e => e);
|
const error = await context.request.get(server.PREFIX + '/test').catch(e => e);
|
||||||
expect(error.message).toBe('apiRequestContext.get: aborted');
|
expect(error.message).toContain('apiRequestContext.get: aborted');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw on network error when sending body after redirect', async ({ context, server }) => {
|
it('should throw on network error when sending body after redirect', async ({ context, server }) => {
|
||||||
|
|
@ -107,7 +107,7 @@ it('should throw on network error when sending body after redirect', async ({ co
|
||||||
req.socket.destroy();
|
req.socket.destroy();
|
||||||
});
|
});
|
||||||
const error = await context.request.get(server.PREFIX + '/redirect').catch(e => e);
|
const error = await context.request.get(server.PREFIX + '/redirect').catch(e => e);
|
||||||
expect(error.message).toBe('apiRequestContext.get: aborted');
|
expect(error.message).toContain('apiRequestContext.get: aborted');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add session cookies to request', async ({ context, server }) => {
|
it('should add session cookies to request', async ({ context, server }) => {
|
||||||
|
|
|
||||||
|
|
@ -322,3 +322,41 @@ test('should print syntax error', async ({ runInlineTest }) => {
|
||||||
expect(result.exitCode).toBe(1);
|
expect(result.exitCode).toBe(1);
|
||||||
expect(result.output).toContain(`Unexpected token "]" while parsing selector "row]"`);
|
expect(result.output).toContain(`Unexpected token "]" while parsing selector "row]"`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should support toBeOK', async ({ runInlineTest, server }) => {
|
||||||
|
const result = await runInlineTest({
|
||||||
|
'a.test.ts': `
|
||||||
|
const { test } = pwt;
|
||||||
|
|
||||||
|
test('pass with response', async ({ page }) => {
|
||||||
|
const res = await page.request.get('${server.EMPTY_PAGE}');
|
||||||
|
await expect(res).toBeOK();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('pass with not', async ({ page }) => {
|
||||||
|
const res = await page.request.get('${server.PREFIX}/unknown');
|
||||||
|
await expect(res).not.toBeOK();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('fail with invalid argument', async ({ page }) => {
|
||||||
|
await expect(page).toBeOK();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('fail with promise', async ({ page }) => {
|
||||||
|
const res = page.request.get('${server.EMPTY_PAGE}').catch(e => {});
|
||||||
|
await expect(res).toBeOK();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('fail', async ({ page }) => {
|
||||||
|
const res = await page.request.get('${server.PREFIX}/unknown');
|
||||||
|
await expect(res).toBeOK();
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
}, { workers: 1 });
|
||||||
|
expect(result.passed).toBe(2);
|
||||||
|
expect(result.failed).toBe(3);
|
||||||
|
expect(result.exitCode).toBe(1);
|
||||||
|
expect(result.output).toContain(`→ GET ${server.PREFIX}/unknown`);
|
||||||
|
expect(result.output).toContain(`← 404 Not Found`);
|
||||||
|
expect(result.output).toContain(`Error: toBeOK can be only used with APIResponse object`);
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue