main repo

This commit is contained in:
Basilosaurusrex
2025-11-24 18:09:40 +01:00
parent b636ee5e70
commit f027651f9b
34146 changed files with 4436636 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
import * as base from '@playwright/test';
import type { NextFixture } from './next-fixture';
import type { NextOptions } from './next-options';
import type { NextWorkerFixture } from './next-worker-fixture';
export * from '@playwright/test';
export type { NextFixture, NextOptions };
export type { FetchHandlerResult } from '../proxy';
export interface NextOptionsConfig {
nextOptions?: NextOptions;
}
export declare function defineConfig<T extends NextOptionsConfig, W>(config: base.PlaywrightTestConfig<T, W>): base.PlaywrightTestConfig<T, W>;
export declare const test: base.TestType<base.PlaywrightTestArgs & base.PlaywrightTestOptions & {
next: NextFixture;
nextOptions: NextOptions;
}, base.PlaywrightWorkerArgs & base.PlaywrightWorkerOptions & {
_nextWorker: NextWorkerFixture;
}>;
export default test;

View File

@@ -0,0 +1,122 @@
// eslint-disable-next-line import/no-extraneous-dependencies
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
defineConfig: null,
test: null,
default: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
defineConfig: function() {
return defineConfig;
},
test: function() {
return test;
},
default: function() {
return _default;
}
});
0 && __export(require("@playwright/test"));
const _test = /*#__PURE__*/ _interop_require_wildcard(_export_star(require("@playwright/test"), exports));
const _nextworkerfixture = require("./next-worker-fixture");
const _nextfixture = require("./next-fixture");
function _export_star(from, to) {
Object.keys(from).forEach(function(k) {
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
Object.defineProperty(to, k, {
enumerable: true,
get: function() {
return from[k];
}
});
}
});
return from;
}
function _getRequireWildcardCache(nodeInterop) {
if (typeof WeakMap !== "function") return null;
var cacheBabelInterop = new WeakMap();
var cacheNodeInterop = new WeakMap();
return (_getRequireWildcardCache = function(nodeInterop) {
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
})(nodeInterop);
}
function _interop_require_wildcard(obj, nodeInterop) {
if (!nodeInterop && obj && obj.__esModule) {
return obj;
}
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
return {
default: obj
};
}
var cache = _getRequireWildcardCache(nodeInterop);
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {};
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
for(var key in obj){
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
function defineConfig(config) {
return _test.defineConfig(config);
}
const test = _test.test.extend({
nextOptions: [
{
fetchLoopback: false
},
{
option: true
}
],
_nextWorker: [
// eslint-disable-next-line no-empty-pattern
async ({}, use)=>{
await (0, _nextworkerfixture.applyNextWorkerFixture)(use);
},
{
scope: "worker",
auto: true
}
],
next: [
async ({ nextOptions, _nextWorker, page }, use, testInfo)=>{
await (0, _nextfixture.applyNextFixture)(use, {
testInfo,
nextWorker: _nextWorker,
page,
nextOptions
});
},
{
auto: true
}
]
});
const _default = test;
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/experimental/testmode/playwright/index.ts"],"names":["defineConfig","test","config","base","extend","nextOptions","fetchLoopback","option","_nextWorker","use","applyNextWorkerFixture","scope","auto","next","page","testInfo","applyNextFixture","nextWorker"],"mappings":"AAAA,6DAA6D;;;;;;;;;;;;;;;;;IAqB7CA,YAAY;eAAZA;;IAMHC,IAAI;eAAJA;;IA2Bb,OAAmB;eAAnB;;;;2EArDsB;mCAIiB;6BACN;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAe1B,SAASD,aACdE,MAAoC;IAEpC,OAAOC,MAAKH,YAAY,CAAIE;AAC9B;AAEO,MAAMD,OAAOE,MAAKF,IAAI,CAACG,MAAM,CAGlC;IACAC,aAAa;QAAC;YAAEC,eAAe;QAAM;QAAG;YAAEC,QAAQ;QAAK;KAAE;IAEzDC,aAAa;QACX,4CAA4C;QAC5C,OAAO,EAAE,EAAEC;YACT,MAAMC,IAAAA,yCAAsB,EAACD;QAC/B;QACA;YAAEE,OAAO;YAAUC,MAAM;QAAK;KAC/B;IAEDC,MAAM;QACJ,OAAO,EAAER,WAAW,EAAEG,WAAW,EAAEM,IAAI,EAAE,EAAEL,KAAKM;YAC9C,MAAMC,IAAAA,6BAAgB,EAACP,KAAK;gBAC1BM;gBACAE,YAAYT;gBACZM;gBACAT;YACF;QACF;QACA;YAAEO,MAAM;QAAK;KACd;AACH;MAEA,WAAeX"}

View File

@@ -0,0 +1,20 @@
import { defineConfig } from './index';
import type { NextFixture } from './next-fixture';
import { type RequestHandler } from 'msw';
export * from 'msw';
export * from '@playwright/test';
export type { NextFixture };
export { defineConfig };
export interface MswFixture {
use: (...handlers: RequestHandler[]) => void;
}
export declare const test: import("@playwright/test").TestType<import("@playwright/test").PlaywrightTestArgs & import("@playwright/test").PlaywrightTestOptions & {
next: NextFixture;
nextOptions: import("./next-options").NextOptions;
} & {
msw: MswFixture;
mswHandlers: RequestHandler[];
}, import("@playwright/test").PlaywrightWorkerArgs & import("@playwright/test").PlaywrightWorkerOptions & {
_nextWorker: import("./next-worker-fixture").NextWorkerFixture;
}>;
export default test;

View File

@@ -0,0 +1,121 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
defineConfig: null,
test: null,
default: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
defineConfig: function() {
return _index.defineConfig;
},
test: function() {
return test;
},
default: function() {
return _default;
}
});
0 && __export(require("msw")) && __export(require("@playwright/test"));
const _index = require("./index");
const _msw = _export_star(require("msw"), exports);
const _stricteventemitter = require("strict-event-emitter");
_export_star(require("@playwright/test"), exports);
function _export_star(from, to) {
Object.keys(from).forEach(function(k) {
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
Object.defineProperty(to, k, {
enumerable: true,
get: function() {
return from[k];
}
});
}
});
return from;
}
const test = _index.test.extend({
mswHandlers: [
[],
{
option: true
}
],
msw: [
async ({ next, mswHandlers }, use)=>{
const handlers = [
...mswHandlers
];
const emitter = new _stricteventemitter.Emitter();
next.onFetch(async (request)=>{
const { body, method, headers, credentials, cache, redirect, integrity, keepalive, mode, destination, referrer, referrerPolicy } = request;
const mockedRequest = new _msw.MockedRequest(new URL(request.url), {
body: body ? await request.arrayBuffer() : undefined,
method,
headers: Object.fromEntries(headers),
credentials,
cache,
redirect,
integrity,
keepalive,
mode,
destination,
referrer,
referrerPolicy
});
let isUnhandled = false;
let isPassthrough = false;
let mockedResponse;
await (0, _msw.handleRequest)(mockedRequest, handlers.slice(0), {
onUnhandledRequest: ()=>{
isUnhandled = true;
}
}, emitter, {
onPassthroughResponse: ()=>{
isPassthrough = true;
},
onMockedResponse: (r)=>{
mockedResponse = r;
}
});
if (isUnhandled) {
return undefined;
}
if (isPassthrough) {
return "continue";
}
if (mockedResponse) {
const { status, headers: responseHeaders, body: responseBody, delay } = mockedResponse;
if (delay) {
await new Promise((resolve)=>setTimeout(resolve, delay));
}
return new Response(responseBody, {
status,
headers: new Headers(responseHeaders)
});
}
return "abort";
});
await use({
use: (...newHandlers)=>{
handlers.unshift(...newHandlers);
}
});
handlers.length = 0;
},
{
auto: true
}
]
});
const _default = test;
//# sourceMappingURL=msw.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/experimental/testmode/playwright/msw.ts"],"names":["defineConfig","test","base","extend","mswHandlers","option","msw","next","use","handlers","emitter","Emitter","onFetch","request","body","method","headers","credentials","cache","redirect","integrity","keepalive","mode","destination","referrer","referrerPolicy","mockedRequest","MockedRequest","URL","url","arrayBuffer","undefined","Object","fromEntries","isUnhandled","isPassthrough","mockedResponse","handleRequest","slice","onUnhandledRequest","onPassthroughResponse","onMockedResponse","r","status","responseHeaders","responseBody","delay","Promise","resolve","setTimeout","Response","Headers","newHandlers","unshift","length","auto"],"mappings":";;;;;;;;;;;;;;;;IAiBSA,YAAY;eAAZA,mBAAY;;IAMRC,IAAI;eAAJA;;IAoGb,OAAmB;eAAnB;;;;uBA3H2C;kCAQpC;oCAEiB;qBAKV;;;;;;;;;;;;;;AAQP,MAAMA,OAAOC,WAAI,CAACC,MAAM,CAG5B;IACDC,aAAa;QAAC,EAAE;QAAE;YAAEC,QAAQ;QAAK;KAAE;IAEnCC,KAAK;QACH,OAAO,EAAEC,IAAI,EAAEH,WAAW,EAAE,EAAEI;YAC5B,MAAMC,WAA6B;mBAAIL;aAAY;YACnD,MAAMM,UAAU,IAAIC,2BAAO;YAE3BJ,KAAKK,OAAO,CAAC,OAAOC;gBAClB,MAAM,EACJC,IAAI,EACJC,MAAM,EACNC,OAAO,EACPC,WAAW,EACXC,KAAK,EACLC,QAAQ,EACRC,SAAS,EACTC,SAAS,EACTC,IAAI,EACJC,WAAW,EACXC,QAAQ,EACRC,cAAc,EACf,GAAGZ;gBACJ,MAAMa,gBAAgB,IAAIC,kBAAa,CAAC,IAAIC,IAAIf,QAAQgB,GAAG,GAAG;oBAC5Df,MAAMA,OAAO,MAAMD,QAAQiB,WAAW,KAAKC;oBAC3ChB;oBACAC,SAASgB,OAAOC,WAAW,CAACjB;oBAC5BC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;oBACAC;gBACF;gBACA,IAAIS,cAAc;gBAClB,IAAIC,gBAAgB;gBACpB,IAAIC;gBACJ,MAAMC,IAAAA,kBAAa,EACjBX,eACAjB,SAAS6B,KAAK,CAAC,IACf;oBACEC,oBAAoB;wBAClBL,cAAc;oBAChB;gBACF,GACAxB,SACA;oBACE8B,uBAAuB;wBACrBL,gBAAgB;oBAClB;oBACAM,kBAAkB,CAACC;wBACjBN,iBAAiBM;oBACnB;gBACF;gBAGF,IAAIR,aAAa;oBACf,OAAOH;gBACT;gBACA,IAAII,eAAe;oBACjB,OAAO;gBACT;gBAEA,IAAIC,gBAAgB;oBAClB,MAAM,EACJO,MAAM,EACN3B,SAAS4B,eAAe,EACxB9B,MAAM+B,YAAY,EAClBC,KAAK,EACN,GAAGV;oBACJ,IAAIU,OAAO;wBACT,MAAM,IAAIC,QAAQ,CAACC,UAAYC,WAAWD,SAASF;oBACrD;oBACA,OAAO,IAAII,SAASL,cAAc;wBAChCF;wBACA3B,SAAS,IAAImC,QAAQP;oBACvB;gBACF;gBAEA,OAAO;YACT;YAEA,MAAMpC,IAAI;gBACRA,KAAK,CAAC,GAAG4C;oBACP3C,SAAS4C,OAAO,IAAID;gBACtB;YACF;YAEA3C,SAAS6C,MAAM,GAAG;QACpB;QACA;YAAEC,MAAM;QAAK;KACd;AACH;MAEA,WAAetD"}

View File

@@ -0,0 +1,12 @@
import type { Page, TestInfo } from '@playwright/test';
import type { NextWorkerFixture, FetchHandler } from './next-worker-fixture';
import type { NextOptions } from './next-options';
export interface NextFixture {
onFetch: (handler: FetchHandler) => void;
}
export declare function applyNextFixture(use: (fixture: NextFixture) => Promise<void>, { testInfo, nextOptions, nextWorker, page, }: {
testInfo: TestInfo;
nextOptions: NextOptions;
nextWorker: NextWorkerFixture;
page: Page;
}): Promise<void>;

View File

@@ -0,0 +1,56 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "applyNextFixture", {
enumerable: true,
get: function() {
return applyNextFixture;
}
});
const _pageroute = require("./page-route");
const _report = require("./report");
class NextFixtureImpl {
constructor(testInfo, options, worker, page){
this.testInfo = testInfo;
this.options = options;
this.worker = worker;
this.page = page;
this.fetchHandlers = [];
this.testId = testInfo.testId;
const testHeaders = {
"Next-Test-Proxy-Port": String(worker.proxyPort),
"Next-Test-Data": this.testId
};
const handleFetch = this.handleFetch.bind(this);
worker.onFetch(this.testId, handleFetch);
this.page.route("**", (route)=>(0, _pageroute.handleRoute)(route, page, testHeaders, handleFetch));
}
teardown() {
this.worker.cleanupTest(this.testId);
}
onFetch(handler) {
this.fetchHandlers.push(handler);
}
async handleFetch(request) {
return (0, _report.reportFetch)(this.testInfo, request, async (req)=>{
for (const handler of this.fetchHandlers.slice().reverse()){
const result = await handler(req.clone());
if (result) {
return result;
}
}
if (this.options.fetchLoopback) {
return fetch(req.clone());
}
return undefined;
});
}
}
async function applyNextFixture(use, { testInfo, nextOptions, nextWorker, page }) {
const fixture = new NextFixtureImpl(testInfo, nextOptions, nextWorker, page);
await use(fixture);
fixture.teardown();
}
//# sourceMappingURL=next-fixture.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/experimental/testmode/playwright/next-fixture.ts"],"names":["applyNextFixture","NextFixtureImpl","constructor","testInfo","options","worker","page","fetchHandlers","testId","testHeaders","String","proxyPort","handleFetch","bind","onFetch","route","handleRoute","teardown","cleanupTest","handler","push","request","reportFetch","req","slice","reverse","result","clone","fetchLoopback","fetch","undefined","use","nextOptions","nextWorker","fixture"],"mappings":";;;;+BAyDsBA;;;eAAAA;;;2BArDM;wBACA;AAM5B,MAAMC;IAIJC,YACUC,UACAC,SACAC,QACAC,KACR;wBAJQH;uBACAC;sBACAC;oBACAC;aANFC,gBAAgC,EAAE;QAQxC,IAAI,CAACC,MAAM,GAAGL,SAASK,MAAM;QAC7B,MAAMC,cAAc;YAClB,wBAAwBC,OAAOL,OAAOM,SAAS;YAC/C,kBAAkB,IAAI,CAACH,MAAM;QAC/B;QACA,MAAMI,cAAc,IAAI,CAACA,WAAW,CAACC,IAAI,CAAC,IAAI;QAC9CR,OAAOS,OAAO,CAAC,IAAI,CAACN,MAAM,EAAEI;QAC5B,IAAI,CAACN,IAAI,CAACS,KAAK,CAAC,MAAM,CAACA,QACrBC,IAAAA,sBAAW,EAACD,OAAOT,MAAMG,aAAaG;IAE1C;IAEAK,WAAiB;QACf,IAAI,CAACZ,MAAM,CAACa,WAAW,CAAC,IAAI,CAACV,MAAM;IACrC;IAEAM,QAAQK,OAAqB,EAAQ;QACnC,IAAI,CAACZ,aAAa,CAACa,IAAI,CAACD;IAC1B;IAEA,MAAcP,YAAYS,OAAgB,EAA+B;QACvE,OAAOC,IAAAA,mBAAW,EAAC,IAAI,CAACnB,QAAQ,EAAEkB,SAAS,OAAOE;YAChD,KAAK,MAAMJ,WAAW,IAAI,CAACZ,aAAa,CAACiB,KAAK,GAAGC,OAAO,GAAI;gBAC1D,MAAMC,SAAS,MAAMP,QAAQI,IAAII,KAAK;gBACtC,IAAID,QAAQ;oBACV,OAAOA;gBACT;YACF;YACA,IAAI,IAAI,CAACtB,OAAO,CAACwB,aAAa,EAAE;gBAC9B,OAAOC,MAAMN,IAAII,KAAK;YACxB;YACA,OAAOG;QACT;IACF;AACF;AAEO,eAAe9B,iBACpB+B,GAA4C,EAC5C,EACE5B,QAAQ,EACR6B,WAAW,EACXC,UAAU,EACV3B,IAAI,EAML;IAED,MAAM4B,UAAU,IAAIjC,gBAAgBE,UAAU6B,aAAaC,YAAY3B;IAEvE,MAAMyB,IAAIG;IAEVA,QAAQjB,QAAQ;AAClB"}

View File

@@ -0,0 +1,3 @@
export interface NextOptions {
fetchLoopback?: boolean;
}

View File

@@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
//# sourceMappingURL=next-options.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":[],"names":[],"mappings":""}

View File

@@ -0,0 +1,8 @@
import type { FetchHandlerResult } from '../proxy';
export type FetchHandler = (request: Request) => FetchHandlerResult | Promise<FetchHandlerResult>;
export interface NextWorkerFixture {
proxyPort: number;
onFetch: (testId: string, handler: FetchHandler) => void;
cleanupTest: (testId: string) => void;
}
export declare function applyNextWorkerFixture(use: (fixture: NextWorkerFixture) => Promise<void>): Promise<void>;

View File

@@ -0,0 +1,49 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "applyNextWorkerFixture", {
enumerable: true,
get: function() {
return applyNextWorkerFixture;
}
});
const _proxy = require("../proxy");
class NextWorkerFixtureImpl {
async setup() {
const server = await (0, _proxy.createProxyServer)({
onFetch: this.handleProxyFetch.bind(this)
});
this.proxyPort = server.port;
this.proxyServer = server;
}
teardown() {
if (this.proxyServer) {
this.proxyServer.close();
this.proxyServer = null;
}
}
cleanupTest(testId) {
this.proxyFetchMap.delete(testId);
}
onFetch(testId, handler) {
this.proxyFetchMap.set(testId, handler);
}
async handleProxyFetch(testId, request) {
const handler = this.proxyFetchMap.get(testId);
return handler == null ? void 0 : handler(request);
}
constructor(){
this.proxyPort = 0;
this.proxyServer = null;
this.proxyFetchMap = new Map();
}
}
async function applyNextWorkerFixture(use) {
const fixture = new NextWorkerFixtureImpl();
await fixture.setup();
await use(fixture);
fixture.teardown();
}
//# sourceMappingURL=next-worker-fixture.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/experimental/testmode/playwright/next-worker-fixture.ts"],"names":["applyNextWorkerFixture","NextWorkerFixtureImpl","setup","server","createProxyServer","onFetch","handleProxyFetch","bind","proxyPort","port","proxyServer","teardown","close","cleanupTest","testId","proxyFetchMap","delete","handler","set","request","get","Map","use","fixture"],"mappings":";;;;+BAmDsBA;;;eAAAA;;;uBAlDY;AAYlC,MAAMC;IAKJ,MAAMC,QAAuB;QAC3B,MAAMC,SAAS,MAAMC,IAAAA,wBAAiB,EAAC;YACrCC,SAAS,IAAI,CAACC,gBAAgB,CAACC,IAAI,CAAC,IAAI;QAC1C;QAEA,IAAI,CAACC,SAAS,GAAGL,OAAOM,IAAI;QAC5B,IAAI,CAACC,WAAW,GAAGP;IACrB;IAEAQ,WAAiB;QACf,IAAI,IAAI,CAACD,WAAW,EAAE;YACpB,IAAI,CAACA,WAAW,CAACE,KAAK;YACtB,IAAI,CAACF,WAAW,GAAG;QACrB;IACF;IAEAG,YAAYC,MAAc,EAAQ;QAChC,IAAI,CAACC,aAAa,CAACC,MAAM,CAACF;IAC5B;IAEAT,QAAQS,MAAc,EAAEG,OAAqB,EAAQ;QACnD,IAAI,CAACF,aAAa,CAACG,GAAG,CAACJ,QAAQG;IACjC;IAEA,MAAcX,iBACZQ,MAAc,EACdK,OAAgB,EACa;QAC7B,MAAMF,UAAU,IAAI,CAACF,aAAa,CAACK,GAAG,CAACN;QACvC,OAAOG,2BAAAA,QAAUE;IACnB;;aAlCOX,YAAoB;aACnBE,cAAkC;aAClCK,gBAAgB,IAAIM;;AAiC9B;AAEO,eAAerB,uBACpBsB,GAAkD;IAElD,MAAMC,UAAU,IAAItB;IACpB,MAAMsB,QAAQrB,KAAK;IACnB,MAAMoB,IAAIC;IACVA,QAAQZ,QAAQ;AAClB"}

View File

@@ -0,0 +1,3 @@
import type { Page, Route } from '@playwright/test';
import type { FetchHandler } from './next-worker-fixture';
export declare function handleRoute(route: Route, page: Page, testHeaders: Record<string, string>, fetchHandler: FetchHandler | null): Promise<void>;

View File

@@ -0,0 +1,59 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "handleRoute", {
enumerable: true,
get: function() {
return handleRoute;
}
});
function continueRoute(route, request, testHeaders) {
return route.continue({
headers: {
...request.headers(),
...testHeaders
}
});
}
async function handleRoute(route, page, testHeaders, fetchHandler) {
const request = route.request();
// Continue the navigation and non-fetch requests.
if (request.isNavigationRequest() || request.resourceType() !== "fetch") {
return continueRoute(route, request, testHeaders);
}
// Continue the local requests. The followup requests will be intercepted
// on the server.
const pageOrigin = new URL(page.url()).origin;
const requestOrigin = new URL(request.url()).origin;
if (pageOrigin === requestOrigin) {
return continueRoute(route, request, testHeaders);
}
if (!fetchHandler) {
return route.abort();
}
const postData = request.postDataBuffer();
const fetchRequest = new Request(request.url(), {
method: request.method(),
headers: Object.fromEntries(Object.entries(request.headers()).filter(([name])=>!name.toLowerCase().startsWith("next-test-"))),
body: postData ?? null
});
const proxyResponse = await fetchHandler(fetchRequest);
if (!proxyResponse) {
return route.abort();
}
if (proxyResponse === "abort") {
return route.abort();
}
if (proxyResponse === "continue") {
return continueRoute(route, request, testHeaders);
}
const { status, headers, body } = proxyResponse;
return route.fulfill({
status,
headers: Object.fromEntries(headers),
body: body ? Buffer.from(await proxyResponse.arrayBuffer()) : undefined
});
}
//# sourceMappingURL=page-route.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/experimental/testmode/playwright/page-route.ts"],"names":["handleRoute","continueRoute","route","request","testHeaders","continue","headers","page","fetchHandler","isNavigationRequest","resourceType","pageOrigin","URL","url","origin","requestOrigin","abort","postData","postDataBuffer","fetchRequest","Request","method","Object","fromEntries","entries","filter","name","toLowerCase","startsWith","body","proxyResponse","status","fulfill","Buffer","from","arrayBuffer","undefined"],"mappings":";;;;+BAgBsBA;;;eAAAA;;;AAbtB,SAASC,cACPC,KAAY,EACZC,OAAgB,EAChBC,WAAmC;IAEnC,OAAOF,MAAMG,QAAQ,CAAC;QACpBC,SAAS;YACP,GAAGH,QAAQG,OAAO,EAAE;YACpB,GAAGF,WAAW;QAChB;IACF;AACF;AAEO,eAAeJ,YACpBE,KAAY,EACZK,IAAU,EACVH,WAAmC,EACnCI,YAAiC;IAEjC,MAAML,UAAUD,MAAMC,OAAO;IAE7B,kDAAkD;IAClD,IAAIA,QAAQM,mBAAmB,MAAMN,QAAQO,YAAY,OAAO,SAAS;QACvE,OAAOT,cAAcC,OAAOC,SAASC;IACvC;IAEA,yEAAyE;IACzE,iBAAiB;IACjB,MAAMO,aAAa,IAAIC,IAAIL,KAAKM,GAAG,IAAIC,MAAM;IAC7C,MAAMC,gBAAgB,IAAIH,IAAIT,QAAQU,GAAG,IAAIC,MAAM;IACnD,IAAIH,eAAeI,eAAe;QAChC,OAAOd,cAAcC,OAAOC,SAASC;IACvC;IAEA,IAAI,CAACI,cAAc;QACjB,OAAON,MAAMc,KAAK;IACpB;IAEA,MAAMC,WAAWd,QAAQe,cAAc;IACvC,MAAMC,eAAe,IAAIC,QAAQjB,QAAQU,GAAG,IAAI;QAC9CQ,QAAQlB,QAAQkB,MAAM;QACtBf,SAASgB,OAAOC,WAAW,CACzBD,OAAOE,OAAO,CAACrB,QAAQG,OAAO,IAAImB,MAAM,CACtC,CAAC,CAACC,KAAK,GAAK,CAACA,KAAKC,WAAW,GAAGC,UAAU,CAAC;QAG/CC,MAAMZ,YAAY;IACpB;IAEA,MAAMa,gBAAgB,MAAMtB,aAAaW;IACzC,IAAI,CAACW,eAAe;QAClB,OAAO5B,MAAMc,KAAK;IACpB;IACA,IAAIc,kBAAkB,SAAS;QAC7B,OAAO5B,MAAMc,KAAK;IACpB;IACA,IAAIc,kBAAkB,YAAY;QAChC,OAAO7B,cAAcC,OAAOC,SAASC;IACvC;IACA,MAAM,EAAE2B,MAAM,EAAEzB,OAAO,EAAEuB,IAAI,EAAE,GAAGC;IAClC,OAAO5B,MAAM8B,OAAO,CAAC;QACnBD;QACAzB,SAASgB,OAAOC,WAAW,CAACjB;QAC5BuB,MAAMA,OAAOI,OAAOC,IAAI,CAAC,MAAMJ,cAAcK,WAAW,MAAMC;IAChE;AACF"}

View File

@@ -0,0 +1,3 @@
import type { TestInfo } from '@playwright/test';
import type { FetchHandler } from './next-worker-fixture';
export declare function reportFetch(testInfo: TestInfo, req: Request, handler: FetchHandler): Promise<Awaited<ReturnType<FetchHandler>>>;

View File

@@ -0,0 +1,127 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "reportFetch", {
enumerable: true,
get: function() {
return reportFetch;
}
});
const _step = require("./step");
async function parseBody(r) {
const contentType = r.headers.get("content-type");
let error;
let text;
let json;
let formData;
let buffer;
if (contentType == null ? void 0 : contentType.includes("text")) {
try {
text = await r.text();
} catch (e) {
error = "failed to parse text";
}
} else if (contentType == null ? void 0 : contentType.includes("json")) {
try {
json = await r.json();
} catch (e) {
error = "failed to parse json";
}
} else if (contentType == null ? void 0 : contentType.includes("form-data")) {
try {
formData = await r.formData();
} catch (e) {
error = "failed to parse formData";
}
} else {
try {
buffer = await r.arrayBuffer();
} catch (e) {
error = "failed to parse arrayBuffer";
}
}
return {
...error ? {
error
} : null,
...text ? {
text
} : null,
...json ? {
json: JSON.stringify(json)
} : null,
...formData ? {
formData: JSON.stringify(Array.from(formData))
} : null,
...buffer && buffer.byteLength > 0 ? {
buffer: `base64;${Buffer.from(buffer).toString("base64")}`
} : null
};
}
function parseHeaders(headers) {
return Object.fromEntries(Array.from(headers).sort(([key1], [key2])=>key1.localeCompare(key2)).map(([key, value])=>{
return [
`header.${key}`,
value
];
}));
}
async function reportFetch(testInfo, req, handler) {
return (0, _step.step)(testInfo, {
title: `next.onFetch: ${req.method} ${req.url}`,
category: "next.onFetch",
apiName: "next.onFetch",
params: {
method: req.method,
url: req.url,
...await parseBody(req.clone()),
...parseHeaders(req.headers)
}
}, async (complete)=>{
const res = await handler(req);
if (res === undefined || res == null) {
complete({
error: {
message: "unhandled"
}
});
} else if (typeof res === "string" && res !== "continue") {
complete({
error: {
message: res
}
});
} else {
let body;
if (typeof res === "string") {
body = {
response: res
};
} else {
const { status, statusText } = res;
body = {
status,
...statusText ? {
statusText
} : null,
...await parseBody(res.clone()),
...parseHeaders(res.headers)
};
}
await (0, _step.step)(testInfo, {
title: `next.onFetch.fulfilled: ${req.method} ${req.url}`,
category: "next.onFetch",
apiName: "next.onFetch.fulfilled",
params: {
...body,
"request.url": req.url,
"request.method": req.method
}
}, async ()=>undefined).catch(()=>undefined);
}
return res;
});
}
//# sourceMappingURL=report.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/experimental/testmode/playwright/report.ts"],"names":["reportFetch","parseBody","r","contentType","headers","get","error","text","json","formData","buffer","includes","e","arrayBuffer","JSON","stringify","Array","from","byteLength","Buffer","toString","parseHeaders","Object","fromEntries","sort","key1","key2","localeCompare","map","key","value","testInfo","req","handler","step","title","method","url","category","apiName","params","clone","complete","res","undefined","message","body","response","status","statusText","catch"],"mappings":"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"}

View File

@@ -0,0 +1,12 @@
import type { TestInfo } from '@playwright/test';
export interface StepProps {
category: string;
title: string;
apiName?: string;
params?: Record<string, string | number | boolean | null | undefined>;
}
type Complete = (result: {
error?: any;
}) => void;
export declare function step<T>(testInfo: TestInfo, props: StepProps, handler: (complete: Complete) => Promise<Awaited<T>>): Promise<Awaited<T>>;
export {};

View File

@@ -0,0 +1,40 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "step", {
enumerable: true,
get: function() {
return step;
}
});
const _test = require("@playwright/test");
function isWithRunAsStep(testInfo) {
return "_runAsStep" in testInfo;
}
async function step(testInfo, props, handler) {
if (isWithRunAsStep(testInfo)) {
return testInfo._runAsStep(props, ({ complete })=>handler(complete));
}
// Fallback to the `test.step()`.
let result;
let reportedError;
try {
console.log(props.title, props);
await _test.test.step(props.title, async ()=>{
result = await handler(({ error })=>{
reportedError = error;
if (reportedError) {
throw reportedError;
}
});
});
} catch (error) {
if (error !== reportedError) {
throw error;
}
}
return result;
}
//# sourceMappingURL=step.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/experimental/testmode/playwright/step.ts"],"names":["step","isWithRunAsStep","testInfo","props","handler","_runAsStep","complete","result","reportedError","console","log","title","test","error"],"mappings":";;;;+BA4BsBA;;;eAAAA;;;sBA1BD;AAoBrB,SAASC,gBACPC,QAAkB;IAElB,OAAO,gBAAgBA;AACzB;AAEO,eAAeF,KACpBE,QAAkB,EAClBC,KAAgB,EAChBC,OAAoD;IAEpD,IAAIH,gBAAgBC,WAAW;QAC7B,OAAOA,SAASG,UAAU,CAACF,OAAO,CAAC,EAAEG,QAAQ,EAAE,GAAKF,QAAQE;IAC9D;IAEA,iCAAiC;IACjC,IAAIC;IACJ,IAAIC;IACJ,IAAI;QACFC,QAAQC,GAAG,CAACP,MAAMQ,KAAK,EAAER;QACzB,MAAMS,UAAI,CAACZ,IAAI,CAACG,MAAMQ,KAAK,EAAE;YAC3BJ,SAAS,MAAMH,QAAQ,CAAC,EAAES,KAAK,EAAE;gBAC/BL,gBAAgBK;gBAChB,IAAIL,eAAe;oBACjB,MAAMA;gBACR;YACF;QACF;IACF,EAAE,OAAOK,OAAO;QACd,IAAIA,UAAUL,eAAe;YAC3B,MAAMK;QACR;IACF;IACA,OAAON;AACT"}

View File

@@ -0,0 +1,4 @@
import type { ProxyFetchRequest, ProxyResponse } from './types';
export type FetchHandlerResult = Response | 'abort' | 'continue' | null | undefined;
export type FetchHandler = (testData: string, request: Request) => FetchHandlerResult | Promise<FetchHandlerResult>;
export declare function handleFetch(req: ProxyFetchRequest, onFetch: FetchHandler): Promise<ProxyResponse>;

View File

@@ -0,0 +1,48 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "handleFetch", {
enumerable: true,
get: function() {
return handleFetch;
}
});
const _types = require("./types");
function buildRequest(req) {
const { request: proxyRequest } = req;
const { url, headers, body, ...options } = proxyRequest;
return new Request(url, {
...options,
headers: new Headers(headers),
body: body ? Buffer.from(body, "base64") : null
});
}
async function buildResponse(response) {
if (!response) {
return _types.UNHANDLED;
}
if (response === "abort") {
return _types.ABORT;
}
if (response === "continue") {
return _types.CONTINUE;
}
const { status, headers, body } = response;
return {
api: "fetch",
response: {
status,
headers: Array.from(headers),
body: body ? Buffer.from(await response.arrayBuffer()).toString("base64") : null
}
};
}
async function handleFetch(req, onFetch) {
const { testData } = req;
const request = buildRequest(req);
const response = await onFetch(testData, request);
return buildResponse(response);
}
//# sourceMappingURL=fetch-api.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/experimental/testmode/proxy/fetch-api.ts"],"names":["handleFetch","buildRequest","req","request","proxyRequest","url","headers","body","options","Request","Headers","Buffer","from","buildResponse","response","UNHANDLED","ABORT","CONTINUE","status","api","Array","arrayBuffer","toString","onFetch","testData"],"mappings":";;;;+BAmDsBA;;;eAAAA;;;uBAlDqB;AAc3C,SAASC,aAAaC,GAAsB;IAC1C,MAAM,EAAEC,SAASC,YAAY,EAAE,GAAGF;IAClC,MAAM,EAAEG,GAAG,EAAEC,OAAO,EAAEC,IAAI,EAAE,GAAGC,SAAS,GAAGJ;IAC3C,OAAO,IAAIK,QAAQJ,KAAK;QACtB,GAAGG,OAAO;QACVF,SAAS,IAAII,QAAQJ;QACrBC,MAAMA,OAAOI,OAAOC,IAAI,CAACL,MAAM,YAAY;IAC7C;AACF;AAEA,eAAeM,cACbC,QAA4B;IAE5B,IAAI,CAACA,UAAU;QACb,OAAOC,gBAAS;IAClB;IACA,IAAID,aAAa,SAAS;QACxB,OAAOE,YAAK;IACd;IACA,IAAIF,aAAa,YAAY;QAC3B,OAAOG,eAAQ;IACjB;IAEA,MAAM,EAAEC,MAAM,EAAEZ,OAAO,EAAEC,IAAI,EAAE,GAAGO;IAClC,OAAO;QACLK,KAAK;QACLL,UAAU;YACRI;YACAZ,SAASc,MAAMR,IAAI,CAACN;YACpBC,MAAMA,OACFI,OAAOC,IAAI,CAAC,MAAME,SAASO,WAAW,IAAIC,QAAQ,CAAC,YACnD;QACN;IACF;AACF;AAEO,eAAetB,YACpBE,GAAsB,EACtBqB,OAAqB;IAErB,MAAM,EAAEC,QAAQ,EAAE,GAAGtB;IACrB,MAAMC,UAAUF,aAAaC;IAC7B,MAAMY,WAAW,MAAMS,QAAQC,UAAUrB;IACzC,OAAOU,cAAcC;AACvB"}

View File

@@ -0,0 +1,3 @@
export { createProxyServer } from './server';
export type { FetchHandler, FetchHandlerResult } from './fetch-api';
export type * from './types';

View File

@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "createProxyServer", {
enumerable: true,
get: function() {
return _server.createProxyServer;
}
});
const _server = require("./server");
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/experimental/testmode/proxy/index.ts"],"names":["createProxyServer"],"mappings":";;;;+BAASA;;;eAAAA,yBAAiB;;;wBAAQ"}

View File

@@ -0,0 +1,5 @@
import type { ProxyServer } from './types';
import type { FetchHandler } from './fetch-api';
export declare function createProxyServer({ onFetch, }: {
onFetch?: FetchHandler;
}): Promise<ProxyServer>;

View File

@@ -0,0 +1,90 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "createProxyServer", {
enumerable: true,
get: function() {
return createProxyServer;
}
});
const _http = /*#__PURE__*/ _interop_require_default(require("http"));
const _types = require("./types");
const _fetchapi = require("./fetch-api");
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function readBody(req) {
return new Promise((resolve, reject)=>{
const acc = [];
req.on("data", (chunk)=>{
acc.push(chunk);
});
req.on("end", ()=>{
resolve(Buffer.concat(acc));
});
req.on("error", reject);
});
}
async function createProxyServer({ onFetch }) {
const server = _http.default.createServer(async (req, res)=>{
if (req.url !== "/") {
res.writeHead(404);
res.end();
return;
}
let json;
try {
json = JSON.parse((await readBody(req)).toString("utf-8"));
} catch (e) {
res.writeHead(400);
res.end();
return;
}
const { api } = json;
let response;
switch(api){
case "fetch":
if (onFetch) {
response = await (0, _fetchapi.handleFetch)(json, onFetch);
}
break;
default:
break;
}
if (!response) {
response = _types.UNHANDLED;
}
res.writeHead(200, {
"Content-Type": "application/json"
});
res.write(JSON.stringify(response));
res.end();
});
await new Promise((resolve)=>{
server.listen(0, "localhost", ()=>{
resolve(undefined);
});
});
const address = server.address();
if (!address || typeof address !== "object") {
server.close();
throw new Error("Failed to create a proxy server");
}
const port = address.port;
const fetchWith = (input, init, testData)=>{
const request = new Request(input, init);
request.headers.set("Next-Test-Proxy-Port", String(port));
request.headers.set("Next-Test-Data", testData ?? "");
return fetch(request);
};
return {
port,
close: ()=>server.close(),
fetchWith
};
}
//# sourceMappingURL=server.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/experimental/testmode/proxy/server.ts"],"names":["createProxyServer","readBody","req","Promise","resolve","reject","acc","on","chunk","push","Buffer","concat","onFetch","server","http","createServer","res","url","writeHead","end","json","JSON","parse","toString","e","api","response","handleFetch","UNHANDLED","write","stringify","listen","undefined","address","close","Error","port","fetchWith","input","init","testData","request","Request","headers","set","String","fetch"],"mappings":";;;;+BAoBsBA;;;eAAAA;;;6DApBL;uBAGS;0BAEE;;;;;;AAE5B,SAASC,SAASC,GAAoB;IACpC,OAAO,IAAIC,QAAgB,CAACC,SAASC;QACnC,MAAMC,MAAgB,EAAE;QACxBJ,IAAIK,EAAE,CAAC,QAAQ,CAACC;YACdF,IAAIG,IAAI,CAACD;QACX;QACAN,IAAIK,EAAE,CAAC,OAAO;YACZH,QAAQM,OAAOC,MAAM,CAACL;QACxB;QACAJ,IAAIK,EAAE,CAAC,SAASF;IAClB;AACF;AAEO,eAAeL,kBAAkB,EACtCY,OAAO,EAGR;IACC,MAAMC,SAASC,aAAI,CAACC,YAAY,CAAC,OAAOb,KAAKc;QAC3C,IAAId,IAAIe,GAAG,KAAK,KAAK;YACnBD,IAAIE,SAAS,CAAC;YACdF,IAAIG,GAAG;YACP;QACF;QAEA,IAAIC;QACJ,IAAI;YACFA,OAAOC,KAAKC,KAAK,CAAC,AAAC,CAAA,MAAMrB,SAASC,IAAG,EAAGqB,QAAQ,CAAC;QACnD,EAAE,OAAOC,GAAG;YACVR,IAAIE,SAAS,CAAC;YACdF,IAAIG,GAAG;YACP;QACF;QAEA,MAAM,EAAEM,GAAG,EAAE,GAAGL;QAEhB,IAAIM;QACJ,OAAQD;YACN,KAAK;gBACH,IAAIb,SAAS;oBACXc,WAAW,MAAMC,IAAAA,qBAAW,EAACP,MAAMR;gBACrC;gBACA;YACF;gBACE;QACJ;QACA,IAAI,CAACc,UAAU;YACbA,WAAWE,gBAAS;QACtB;QAEAZ,IAAIE,SAAS,CAAC,KAAK;YAAE,gBAAgB;QAAmB;QACxDF,IAAIa,KAAK,CAACR,KAAKS,SAAS,CAACJ;QACzBV,IAAIG,GAAG;IACT;IAEA,MAAM,IAAIhB,QAAQ,CAACC;QACjBS,OAAOkB,MAAM,CAAC,GAAG,aAAa;YAC5B3B,QAAQ4B;QACV;IACF;IAEA,MAAMC,UAAUpB,OAAOoB,OAAO;IAC9B,IAAI,CAACA,WAAW,OAAOA,YAAY,UAAU;QAC3CpB,OAAOqB,KAAK;QACZ,MAAM,IAAIC,MAAM;IAClB;IACA,MAAMC,OAAOH,QAAQG,IAAI;IAEzB,MAAMC,YAAsC,CAACC,OAAOC,MAAMC;QACxD,MAAMC,UAAU,IAAIC,QAAQJ,OAAOC;QACnCE,QAAQE,OAAO,CAACC,GAAG,CAAC,wBAAwBC,OAAOT;QACnDK,QAAQE,OAAO,CAACC,GAAG,CAAC,kBAAkBJ,YAAY;QAClD,OAAOM,MAAML;IACf;IAEA,OAAO;QAAEL;QAAMF,OAAO,IAAMrB,OAAOqB,KAAK;QAAIG;IAAU;AACxD"}

View File

@@ -0,0 +1,43 @@
export interface ProxyServer {
readonly port: number;
fetchWith(input: string | URL, init?: RequestInit, testData?: string): Promise<Response>;
close(): void;
}
interface ProxyRequestBase {
testData: string;
api: string;
}
interface ProxyResponseBase {
api: string;
}
export interface ProxyUnhandledResponse extends ProxyResponseBase {
api: 'unhandled';
}
export interface ProxyAbortResponse extends ProxyResponseBase {
api: 'abort';
}
export interface ProxyContinueResponse extends ProxyResponseBase {
api: 'continue';
}
export interface ProxyFetchRequest extends ProxyRequestBase {
api: 'fetch';
request: {
url: string;
headers: Array<[string, string]>;
body: string | null;
} & Omit<RequestInit, 'headers' | 'body'>;
}
export interface ProxyFetchResponse extends ProxyResponseBase {
api: 'fetch';
response: {
status: number;
headers: Array<[string, string]>;
body: string | null;
};
}
export type ProxyRequest = ProxyFetchRequest;
export type ProxyResponse = ProxyUnhandledResponse | ProxyAbortResponse | ProxyContinueResponse | ProxyFetchResponse;
export declare const ABORT: ProxyResponse;
export declare const CONTINUE: ProxyResponse;
export declare const UNHANDLED: ProxyResponse;
export {};

View File

@@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
ABORT: null,
CONTINUE: null,
UNHANDLED: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
ABORT: function() {
return ABORT;
},
CONTINUE: function() {
return CONTINUE;
},
UNHANDLED: function() {
return UNHANDLED;
}
});
const ABORT = {
api: "abort"
};
const CONTINUE = {
api: "continue"
};
const UNHANDLED = {
api: "unhandled"
};
//# sourceMappingURL=types.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/experimental/testmode/proxy/types.ts"],"names":["ABORT","CONTINUE","UNHANDLED","api"],"mappings":";;;;;;;;;;;;;;;;IAyDaA,KAAK;eAALA;;IACAC,QAAQ;eAARA;;IACAC,SAAS;eAATA;;;AAFN,MAAMF,QAAuB;IAAEG,KAAK;AAAQ;AAC5C,MAAMF,WAA0B;IAAEE,KAAK;AAAW;AAClD,MAAMD,YAA2B;IAAEC,KAAK;AAAY"}

View File

@@ -0,0 +1,5 @@
import { WorkerRequestHandler } from '../../server/lib/setup-server-worker';
import { NodeRequestHandler } from '../../server/next-server';
export declare function interceptTestApis(): () => void;
export declare function wrapRequestHandlerWorker(handler: WorkerRequestHandler): WorkerRequestHandler;
export declare function wrapRequestHandlerNode(handler: NodeRequestHandler): NodeRequestHandler;

171
node_modules/next/dist/experimental/testmode/server.js generated vendored Normal file
View File

@@ -0,0 +1,171 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
interceptTestApis: null,
wrapRequestHandlerWorker: null,
wrapRequestHandlerNode: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
interceptTestApis: function() {
return interceptTestApis;
},
wrapRequestHandlerWorker: function() {
return wrapRequestHandlerWorker;
},
wrapRequestHandlerNode: function() {
return wrapRequestHandlerNode;
}
});
const _async_hooks = require("async_hooks");
const _ClientRequest = require("next/dist/compiled/@mswjs/interceptors/ClientRequest");
const testStorage = new _async_hooks.AsyncLocalStorage();
function getTestStack() {
let stack = (new Error().stack ?? "").split("\n");
// Skip the first line and find first non-empty line.
for(let i = 1; i < stack.length; i++){
if (stack[i].length > 0) {
stack = stack.slice(i);
break;
}
}
// Filter out franmework lines.
stack = stack.filter((f)=>!f.includes("/next/dist/"));
// At most 5 lines.
stack = stack.slice(0, 5);
// Cleanup some internal info and trim.
stack = stack.map((s)=>s.replace("webpack-internal:///(rsc)/", "").trim());
return stack.join(" ");
}
async function buildProxyRequest(testData, request) {
const { url, method, headers, body, cache, credentials, integrity, mode, redirect, referrer, referrerPolicy } = request;
return {
testData,
api: "fetch",
request: {
url,
method,
headers: [
...Array.from(headers),
[
"next-test-stack",
getTestStack()
]
],
body: body ? Buffer.from(await request.arrayBuffer()).toString("base64") : null,
cache,
credentials,
integrity,
mode,
redirect,
referrer,
referrerPolicy
}
};
}
function buildResponse(proxyResponse) {
const { status, headers, body } = proxyResponse.response;
return new Response(body ? Buffer.from(body, "base64") : null, {
status,
headers: new Headers(headers)
});
}
async function handleFetch(originalFetch, request) {
const testInfo = testStorage.getStore();
if (!testInfo) {
throw new Error("No test info");
}
const { testData, proxyPort } = testInfo;
const proxyRequest = await buildProxyRequest(testData, request);
const resp = await originalFetch(`http://localhost:${proxyPort}`, {
method: "POST",
body: JSON.stringify(proxyRequest)
});
if (!resp.ok) {
throw new Error(`Proxy request failed: ${resp.status}`);
}
const proxyResponse = await resp.json();
const { api } = proxyResponse;
switch(api){
case "continue":
return originalFetch(request);
case "abort":
case "unhandled":
throw new Error(`Proxy request aborted [${request.method} ${request.url}]`);
default:
break;
}
return buildResponse(proxyResponse);
}
function interceptFetch() {
const originalFetch = global.fetch;
global.fetch = function testFetch(input, init) {
var _init_next;
// Passthrough internal requests.
// @ts-ignore
if (init == null ? void 0 : (_init_next = init.next) == null ? void 0 : _init_next.internal) {
return originalFetch(input, init);
}
return handleFetch(originalFetch, new Request(input, init));
};
}
function interceptTestApis() {
const originalFetch = global.fetch;
interceptFetch();
const clientRequestInterceptor = new _ClientRequest.ClientRequestInterceptor();
clientRequestInterceptor.on("request", async ({ request })=>{
const response = await handleFetch(originalFetch, request);
request.respondWith(response);
});
clientRequestInterceptor.apply();
// Cleanup.
return ()=>{
clientRequestInterceptor.dispose();
global.fetch = originalFetch;
};
}
function wrapRequestHandlerWorker(handler) {
return async (req, res)=>{
const proxyPortHeader = req.headers["next-test-proxy-port"];
if (!proxyPortHeader) {
await handler(req, res);
return;
}
const url = req.url ?? "";
const proxyPort = Number(proxyPortHeader);
const testData = req.headers["next-test-data"] ?? "";
const testReqInfo = {
url,
proxyPort,
testData
};
await testStorage.run(testReqInfo, ()=>handler(req, res));
};
}
function wrapRequestHandlerNode(handler) {
return async (req, res, parsedUrl)=>{
const proxyPortHeader = req.headers["next-test-proxy-port"];
if (!proxyPortHeader) {
await handler(req, res, parsedUrl);
return;
}
const url = req.url ?? "";
const proxyPort = Number(proxyPortHeader);
const testData = req.headers["next-test-data"] ?? "";
const testReqInfo = {
url,
proxyPort,
testData
};
await testStorage.run(testReqInfo, ()=>handler(req, res, parsedUrl));
};
}
//# sourceMappingURL=server.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../src/experimental/testmode/server.ts"],"names":["interceptTestApis","wrapRequestHandlerWorker","wrapRequestHandlerNode","testStorage","AsyncLocalStorage","getTestStack","stack","Error","split","i","length","slice","filter","f","includes","map","s","replace","trim","join","buildProxyRequest","testData","request","url","method","headers","body","cache","credentials","integrity","mode","redirect","referrer","referrerPolicy","api","Array","from","Buffer","arrayBuffer","toString","buildResponse","proxyResponse","status","response","Response","Headers","handleFetch","originalFetch","testInfo","getStore","proxyPort","proxyRequest","resp","JSON","stringify","ok","json","interceptFetch","global","fetch","testFetch","input","init","next","internal","Request","clientRequestInterceptor","ClientRequestInterceptor","on","respondWith","apply","dispose","handler","req","res","proxyPortHeader","Number","testReqInfo","run","parsedUrl"],"mappings":"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"}