UNPKG

playwright-fluent

Version:
200 lines (199 loc) 7.72 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.withMocks = exports.spreadMissingProperties = exports.inferMockResponseTypeIfNeeded = exports.getMockStatus = exports.defaultMocksOptions = exports.passthroughMock = exports.getPostDataOf = exports.noopVoidFunc = void 0; const utils_1 = require("../../../utils"); function noopVoidFunc() { // do nothing } exports.noopVoidFunc = noopVoidFunc; function getPostDataOf(request) { try { return request.postDataJSON(); } catch (error) { return request.postData(); } } exports.getPostDataOf = getPostDataOf; exports.passthroughMock = { displayName: 'passthroughMock', urlMatcher: () => true, methodMatcher: () => true, queryStringMatcher: () => true, postDataMatcher: () => true, contextMatcher: () => true, customMatcher: () => true, enrichResponseHeaders: (headers) => headers, responseType: 'continue', status: 200, jsonResponse: () => { return {}; }, rawResponse: () => '', delayInMilliseconds: 0, updateData: noopVoidFunc, lastUpdated: () => new Date(), updatePolicy: 'always', }; exports.defaultMocksOptions = { // eslint-disable-next-line @typescript-eslint/no-empty-function onMockNotFound: () => { }, // eslint-disable-next-line @typescript-eslint/no-empty-function onMockFound: () => { }, // eslint-disable-next-line @typescript-eslint/no-empty-function onInternalError: () => { }, }; function getMockStatus(mock, requestInfos) { if (typeof mock.status === 'function') { return mock.status(requestInfos); } if (typeof mock.status === 'number') { return mock.status; } return 200; } exports.getMockStatus = getMockStatus; function inferMockResponseTypeIfNeeded(mock) { if (mock.responseType) { return mock; } if (typeof mock.jsonResponse === 'function' && typeof mock.rawResponse !== 'function') { return { ...mock, responseType: 'json', }; } if (typeof mock.rawResponse === 'function' && typeof mock.jsonResponse !== 'function') { return { ...mock, responseType: 'string', }; } if (typeof mock.rawResponse !== 'function' && typeof mock.jsonResponse !== 'function') { return { ...mock, responseType: 'empty', }; } return mock; } exports.inferMockResponseTypeIfNeeded = inferMockResponseTypeIfNeeded; function spreadMissingProperties(mock) { return { ...exports.passthroughMock, displayName: 'not set', ...mock }; } exports.spreadMissingProperties = spreadMissingProperties; async function fullfillRouteWithMock(mock, route, options) { if (mock.delayInMilliseconds > 0) { setTimeout(() => route.fulfill(options), mock.delayInMilliseconds); return; } route.fulfill(options); } async function withMocks(mocks, context, options, page) { if (typeof mocks !== 'function') { throw new Error(`mocks must be a function that returns an array of FluentMock objects.`); } if (!Array.isArray(mocks())) { throw new Error(`mocks must be a function that returns an array of FluentMock objects.`); } if (!page) { throw new Error(`Cannot intercept requests with mocks because no browser has been launched`); } const mockOptions = { ...exports.defaultMocksOptions, ...options, }; await page.route((uri) => { if (mocks().length === 0) { return false; } const mockExists = mocks() .map(inferMockResponseTypeIfNeeded) .map(spreadMissingProperties) .map((mock) => mock.urlMatcher(uri.toString())) .some((match) => match === true); return mockExists; }, (route, request) => { const requestMethod = request.method(); const url = request.url(); const queryString = (0, utils_1.extractQueryStringObjectFromUrl)(url); const postData = getPostDataOf(request); const sharedContext = context(); const requestInfos = { request, queryString, postData, sharedContext }; const mock = mocks() .map(inferMockResponseTypeIfNeeded) .map(spreadMissingProperties) .filter((mock) => mock.urlMatcher(url)) .filter((mock) => mock.methodMatcher(requestMethod)) .filter((mock) => mock.queryStringMatcher(queryString)) .filter((mock) => mock.postDataMatcher(postData)) .filter((mock) => mock.contextMatcher(sharedContext)) .filter((mock) => mock.customMatcher(requestInfos)) .pop(); if (!mock) { mockOptions.onMockNotFound(requestInfos); route.continue(); return; } if (mock.responseType === 'continue' && mock.delayInMilliseconds === 0) { route.continue(); return; } if (mock.responseType === 'continue' && mock.delayInMilliseconds > 0) { setTimeout(() => route.continue(), mock.delayInMilliseconds); return; } if (mock.responseType === 'json') { const responseObject = mock.jsonResponse(requestInfos); const headers = mock.enrichResponseHeaders({ 'Access-Control-Allow-Credentials': 'true', 'Access-Control-Allow-Origin': '*', }); const status = getMockStatus(mock, requestInfos); const body = JSON.stringify(responseObject); const contentType = 'application/json'; mockOptions.onMockFound(mock, requestInfos); fullfillRouteWithMock(mock, route, { status, headers, contentType, body }); return; } if (mock.responseType === 'string') { const headers = mock.enrichResponseHeaders({ 'Access-Control-Allow-Credentials': 'true', 'Access-Control-Allow-Origin': '*', }); const status = getMockStatus(mock, requestInfos); const body = mock.rawResponse(requestInfos); const contentType = 'text/plain'; mockOptions.onMockFound(mock, requestInfos); fullfillRouteWithMock(mock, route, { status, headers, contentType, body }); return; } if (mock.responseType === 'empty') { const headers = mock.enrichResponseHeaders({ 'Access-Control-Allow-Credentials': 'true', 'Access-Control-Allow-Origin': '*', }); const status = getMockStatus(mock, requestInfos); const body = ''; const contentType = 'text/plain'; mockOptions.onMockFound(mock, requestInfos); fullfillRouteWithMock(mock, route, { status, headers, contentType, body }); return; } if (mock.responseType === 'javascript') { const headers = mock.enrichResponseHeaders({ 'access-control-allow-methods': '*', 'Access-Control-Allow-Credentials': 'true', 'Access-Control-Allow-Origin': '*', }); const status = getMockStatus(mock, requestInfos); const body = mock.rawResponse(requestInfos); const contentType = 'application/javascript'; mockOptions.onMockFound(mock, requestInfos); fullfillRouteWithMock(mock, route, { status, headers, contentType, body }); return; } throw new Error(`mock with response type '${mock.responseType}' is not yet implemented`); }); } exports.withMocks = withMocks;