Spaces:
Paused
Paused
Download node_modules/playwright/lib/index.js from ThomasHeisig/Brain-5D-Space: direct link, hf CLI and curl.
- Browser
- Download file 36.5 kB
-
https://huggingface.co/spaces/ThomasHeisig/Brain-5D-Space/resolve/main/node_modules/playwright/lib/index.js
- Command line
-
hf download hf://spaces/ThomasHeisig/Brain-5D-Space/node_modules/playwright/lib/index.js
-
curl -L -o index.js https://huggingface.co/spaces/ThomasHeisig/Brain-5D-Space/resolve/main/node_modules/playwright/lib/index.js
36.5 kB
| ; | |
| var __create = Object.create; | |
| var __defProp = Object.defineProperty; | |
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | |
| var __getOwnPropNames = Object.getOwnPropertyNames; | |
| var __getProtoOf = Object.getPrototypeOf; | |
| var __hasOwnProp = Object.prototype.hasOwnProperty; | |
| var __export = (target, all) => { | |
| for (var name in all) | |
| __defProp(target, name, { get: all[name], enumerable: true }); | |
| }; | |
| var __copyProps = (to, from, except, desc) => { | |
| if (from && typeof from === "object" || typeof from === "function") { | |
| for (let key of __getOwnPropNames(from)) | |
| if (!__hasOwnProp.call(to, key) && key !== except) | |
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | |
| } | |
| return to; | |
| }; | |
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | |
| // If the importer is in node compatibility mode or this is not an ESM | |
| // file that has been converted to a CommonJS file using a Babel- | |
| // compatible transform (i.e. "__esModule" has not been set), then set | |
| // "default" to the CommonJS "module.exports" for node compatibility. | |
| isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, | |
| mod | |
| )); | |
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | |
| var index_exports = {}; | |
| __export(index_exports, { | |
| _baseTest: () => _baseTest, | |
| _utilityTest: () => _utilityTest, | |
| defineConfig: () => import_common2.defineConfig, | |
| expect: () => import_expect.expect, | |
| mergeExpects: () => import_expect2.mergeExpects, | |
| mergeTests: () => import_common2.mergeTests, | |
| test: () => test | |
| }); | |
| module.exports = __toCommonJS(index_exports); | |
| var import_fs = __toESM(require("fs")); | |
| var import_path = __toESM(require("path")); | |
| var playwrightLibrary = __toESM(require("playwright-core")); | |
| var import_errorContext = require("./errorContext"); | |
| var import_common = require("./common"); | |
| var globals = __toESM(require("./globals")); | |
| var import_browserBackend = require("./mcp/test/browserBackend"); | |
| var import_expect = require("./matchers/expect"); | |
| var import_common2 = require("./common"); | |
| var import_expect2 = require("./matchers/expect"); | |
| const { getActionGroup, renderParamsForCall, renderSubtitleForCall, renderTitleForCall, truncateParam } = require("playwright-core/lib/coreBundle").iso; | |
| const { escapeHTML } = require("playwright-core/lib/coreBundle").iso; | |
| const { jsonStringifyForceASCII } = require("playwright-core/lib/coreBundle").utils; | |
| const { createGuid } = require("playwright-core/lib/coreBundle").utils; | |
| const { debugMode } = require("playwright-core/lib/coreBundle").utils; | |
| const { debugLogger } = require("playwright-core/lib/coreBundle").utils; | |
| const { currentZone } = require("playwright-core/lib/coreBundle").utils; | |
| const _baseTest = import_common.testType.rootTestType.test; | |
| if (process["__pw_initiator__"]) { | |
| const originalStackTraceLimit = Error.stackTraceLimit; | |
| Error.stackTraceLimit = 200; | |
| try { | |
| throw new Error("Requiring @playwright/test second time, \nFirst:\n" + process["__pw_initiator__"] + "\n\nSecond: "); | |
| } finally { | |
| Error.stackTraceLimit = originalStackTraceLimit; | |
| } | |
| } else { | |
| process["__pw_initiator__"] = new Error().stack; | |
| } | |
| const utilityFixtures = { | |
| playwright: [async ({}, use) => { | |
| await use(require("playwright-core")); | |
| }, { scope: "worker", box: true }], | |
| screenshot: ["off", { scope: "worker", option: true, box: true }], | |
| trace: ["off", { scope: "worker", option: true, box: true }], | |
| testIdAttribute: ["data-testid", { option: true, box: true }], | |
| _combinedContextOptions: [{}, { box: true }], | |
| _setupArtifacts: [async ({ playwright, screenshot, _combinedContextOptions }, use, testInfo) => { | |
| testInfo.setTimeout(testInfo.project.timeout); | |
| const artifactsRecorder = new ArtifactsRecorder(playwright, tracing().artifactsDir(), screenshot); | |
| await artifactsRecorder.willStartTest(testInfo); | |
| const tracingGroupSteps = []; | |
| const pausedContexts = /* @__PURE__ */ new Set(); | |
| const csiListener = { | |
| onApiCallBegin: (data, channel) => { | |
| const testInfo2 = globals.currentTestInfo(); | |
| if (!testInfo2) | |
| return; | |
| if (channel.type === "Tracing" && channel.method === "tracingGroupEnd") { | |
| data.userData = (error) => tracingGroupSteps.pop()?.complete({ error }); | |
| return; | |
| } | |
| const zone = currentZone().data("stepZone"); | |
| const isExpectCall = channel.type === "Frame" && channel.method === "expect" || channel.type === "Page" && channel.method === "expectScreenshot"; | |
| if (zone && zone.category === "expect" && isExpectCall) { | |
| data.stepId = zone.stepId; | |
| return; | |
| } | |
| const params = renderParamsForCall({ type: channel.type, method: channel.method, params: channel.params }); | |
| const step = testInfo2._addStep({ | |
| location: data.frames[0], | |
| category: "pw:api", | |
| title: renderTitle(channel.type, channel.method, channel.params, data.title), | |
| subtitle: renderSubtitle(channel.type, channel.method, channel.params), | |
| params, | |
| group: getActionGroup({ type: channel.type, method: channel.method }) | |
| }, tracingGroupSteps[tracingGroupSteps.length - 1]); | |
| data.stepId = step.stepId; | |
| if (channel.type === "Tracing" && channel.method === "tracingGroup") { | |
| tracingGroupSteps.push(step); | |
| } else { | |
| data.userData = (error) => step.complete({ error }); | |
| } | |
| }, | |
| onApiCallEnd: (data) => { | |
| const completeStep = data.userData; | |
| completeStep?.(data.error); | |
| }, | |
| onWillPause: ({ keepTestTimeout }) => { | |
| if (!keepTestTimeout) | |
| globals.currentTestInfo()?._setIgnoreTimeouts(true); | |
| }, | |
| runBeforeCreateBrowserContext: async (options) => { | |
| for (const [key, value] of Object.entries(_combinedContextOptions)) { | |
| if (!(key in options)) | |
| options[key] = value; | |
| } | |
| }, | |
| runBeforeCreateRequestContext: async (options) => { | |
| for (const [key, value] of Object.entries(_combinedContextOptions)) { | |
| if (!(key in options)) | |
| options[key] = value; | |
| } | |
| }, | |
| runAfterCreateBrowserContext: async (context) => { | |
| context.debugger.on("pausedstatechanged", () => { | |
| const paused = !!context.debugger.pausedDetails(); | |
| if (pausedContexts.has(context) && !paused) { | |
| pausedContexts.delete(context); | |
| testInfo._setIgnoreTimeouts(false); | |
| } else if (!pausedContexts.has(context) && paused) { | |
| pausedContexts.add(context); | |
| testInfo._setIgnoreTimeouts(true); | |
| } | |
| }); | |
| await artifactsRecorder.didCreateBrowserContext(context); | |
| const currentTestInfo = globals.currentTestInfo(); | |
| if (currentTestInfo) { | |
| attachConnectedHeaderIfNeeded(currentTestInfo, context.browser()); | |
| currentTestInfo._onCustomMessageCallback = (0, import_browserBackend.createCustomMessageHandler)(currentTestInfo, context); | |
| await (0, import_browserBackend.runDaemonForContext)(currentTestInfo, context); | |
| } | |
| }, | |
| runAfterCreateRequestContext: async (context) => { | |
| await artifactsRecorder.didCreateRequestContext(context); | |
| }, | |
| runBeforeCloseBrowserContext: async (context) => { | |
| await artifactsRecorder.willCloseBrowserContext(context); | |
| }, | |
| runBeforeCloseRequestContext: async (context) => { | |
| await artifactsRecorder.willCloseRequestContext(context); | |
| } | |
| }; | |
| const clientInstrumentation = playwright._instrumentation; | |
| clientInstrumentation.addListener(csiListener); | |
| await use(); | |
| clientInstrumentation.removeListener(csiListener); | |
| await artifactsRecorder.didFinishTest(); | |
| }, { auto: "all-hooks-included", title: "trace recording", box: true, timeout: 0 }], | |
| request: async ({ playwright }, use) => { | |
| const request = await playwright.request.newContext(); | |
| await use(request); | |
| const hook = test.info()._currentHookType(); | |
| if (hook === "beforeAll") { | |
| await request.dispose({ reason: [ | |
| `Fixture { request } from beforeAll cannot be reused in a test.`, | |
| ` - Recommended fix: use a separate { request } in the test.`, | |
| ` - Alternatively, manually create APIRequestContext in beforeAll and dispose it in afterAll.`, | |
| `See https://playwright.dev/docs/api-testing#sending-api-requests-from-ui-tests for more details.` | |
| ].join("\n") }); | |
| } else { | |
| await request.dispose(); | |
| } | |
| } | |
| }; | |
| const _utilityTest = _baseTest.extend(utilityFixtures); | |
| const playwrightFixtures = { | |
| defaultBrowserType: ["chromium", { scope: "worker", option: true, box: true }], | |
| browserName: [({ defaultBrowserType }, use) => use(defaultBrowserType), { scope: "worker", option: true, box: true }], | |
| headless: [({ launchOptions }, use) => use(launchOptions.headless ?? true), { scope: "worker", option: true, box: true }], | |
| channel: [({ launchOptions }, use) => use(launchOptions.channel), { scope: "worker", option: true, box: true }], | |
| launchOptions: [{}, { scope: "worker", option: true, box: true }], | |
| connectOptions: [async ({ _optionConnectOptions }, use) => { | |
| await use(connectOptionsFromEnv() || _optionConnectOptions); | |
| }, { scope: "worker", option: true, box: true }], | |
| video: ["off", { scope: "worker", option: true, box: true }], | |
| _browserOptions: [async ({ playwright, headless, channel, launchOptions }, use) => { | |
| const options = { | |
| handleSIGINT: false, | |
| ...launchOptions, | |
| tracesDir: tracing().tracesDir(), | |
| artifactsDir: tracing().artifactsDir() | |
| }; | |
| if (headless !== void 0) | |
| options.headless = headless; | |
| if (channel !== void 0) | |
| options.channel = channel; | |
| playwright._defaultLaunchOptions = options; | |
| await use(options); | |
| playwright._defaultLaunchOptions = void 0; | |
| }, { scope: "worker", auto: true, box: true }], | |
| browser: [async ({ playwright, browserName, _browserOptions, connectOptions }, use, workerInfo) => { | |
| if (!["chromium", "firefox", "webkit"].includes(browserName)) | |
| throw new Error(`Unexpected browserName "${browserName}", must be one of "chromium", "firefox" or "webkit"`); | |
| if (connectOptions) { | |
| const browser2 = await playwright[browserName].connect(connectOptions.wsEndpoint, { | |
| ...connectOptions, | |
| exposeNetwork: connectOptions.exposeNetwork, | |
| headers: { | |
| // HTTP headers are ASCII only (not UTF-8). | |
| "x-playwright-launch-options": jsonStringifyForceASCII(_browserOptions), | |
| ...connectOptions.headers | |
| } | |
| }); | |
| await use(browser2); | |
| await browser2.close({ reason: "Test ended." }); | |
| return; | |
| } | |
| const browser = await playwright[browserName].launch(); | |
| if (process.env.PLAYWRIGHT_DASHBOARD) | |
| await browser.bind(`worker-${workerInfo.parallelIndex}`); | |
| await use(browser); | |
| await browser.close({ reason: "Test ended." }); | |
| }, { scope: "worker", timeout: 0 }], | |
| acceptDownloads: [({ contextOptions }, use) => use(contextOptions.acceptDownloads ?? true), { option: true, box: true }], | |
| bypassCSP: [({ contextOptions }, use) => use(contextOptions.bypassCSP ?? false), { option: true, box: true }], | |
| colorScheme: [({ contextOptions }, use) => use(contextOptions.colorScheme === void 0 ? "light" : contextOptions.colorScheme), { option: true, box: true }], | |
| contrast: [({ contextOptions }, use) => use(contextOptions.contrast === void 0 ? "no-preference" : contextOptions.contrast), { option: true, box: true }], | |
| deviceScaleFactor: [({ contextOptions }, use) => use(contextOptions.deviceScaleFactor), { option: true, box: true }], | |
| extraHTTPHeaders: [({ contextOptions }, use) => use(contextOptions.extraHTTPHeaders), { option: true, box: true }], | |
| forcedColors: [({ contextOptions }, use) => use(contextOptions.forcedColors === void 0 ? "none" : contextOptions.forcedColors), { option: true, box: true }], | |
| geolocation: [({ contextOptions }, use) => use(contextOptions.geolocation), { option: true, box: true }], | |
| hasTouch: [({ contextOptions }, use) => use(contextOptions.hasTouch ?? false), { option: true, box: true }], | |
| httpCredentials: [({ contextOptions }, use) => use(contextOptions.httpCredentials), { option: true, box: true }], | |
| ignoreHTTPSErrors: [({ contextOptions }, use) => use(contextOptions.ignoreHTTPSErrors ?? false), { option: true, box: true }], | |
| isMobile: [({ contextOptions }, use) => use(contextOptions.isMobile ?? false), { option: true, box: true }], | |
| javaScriptEnabled: [({ contextOptions }, use) => use(contextOptions.javaScriptEnabled ?? true), { option: true, box: true }], | |
| locale: [({ contextOptions }, use) => use(contextOptions.locale ?? "en-US"), { option: true, box: true }], | |
| offline: [({ contextOptions }, use) => use(contextOptions.offline ?? false), { option: true, box: true }], | |
| permissions: [({ contextOptions }, use) => use(contextOptions.permissions), { option: true, box: true }], | |
| proxy: [({ contextOptions }, use) => use(contextOptions.proxy), { option: true, box: true }], | |
| reducedMotion: [({ contextOptions }, use) => use(contextOptions.reducedMotion === void 0 ? "no-preference" : contextOptions.reducedMotion), { option: true, box: true }], | |
| storageState: [({ contextOptions }, use) => use(contextOptions.storageState), { option: true, box: true }], | |
| clientCertificates: [({ contextOptions }, use) => use(contextOptions.clientCertificates), { option: true, box: true }], | |
| timezoneId: [({ contextOptions }, use) => use(contextOptions.timezoneId), { option: true, box: true }], | |
| userAgent: [({ contextOptions }, use) => use(contextOptions.userAgent), { option: true, box: true }], | |
| viewport: [({ contextOptions }, use) => use(contextOptions.viewport === void 0 ? { width: 1280, height: 720 } : contextOptions.viewport), { option: true, box: true }], | |
| actionTimeout: [0, { option: true, box: true }], | |
| navigationTimeout: [0, { option: true, box: true }], | |
| baseURL: [async ({}, use) => { | |
| await use(process.env.PLAYWRIGHT_TEST_BASE_URL); | |
| }, { option: true, box: true }], | |
| serviceWorkers: [({ contextOptions }, use) => use(contextOptions.serviceWorkers ?? "allow"), { option: true, box: true }], | |
| contextOptions: [{}, { option: true, box: true }], | |
| _combinedContextOptions: [async ({ | |
| acceptDownloads, | |
| bypassCSP, | |
| clientCertificates, | |
| colorScheme, | |
| contrast, | |
| deviceScaleFactor, | |
| extraHTTPHeaders, | |
| forcedColors, | |
| hasTouch, | |
| geolocation, | |
| httpCredentials, | |
| ignoreHTTPSErrors, | |
| isMobile, | |
| javaScriptEnabled, | |
| locale, | |
| offline, | |
| permissions, | |
| proxy, | |
| reducedMotion, | |
| storageState, | |
| viewport, | |
| timezoneId, | |
| userAgent, | |
| baseURL, | |
| contextOptions, | |
| serviceWorkers | |
| }, use, testInfo) => { | |
| const options = {}; | |
| if (acceptDownloads !== void 0) | |
| options.acceptDownloads = acceptDownloads; | |
| if (bypassCSP !== void 0) | |
| options.bypassCSP = bypassCSP; | |
| if (colorScheme !== void 0) | |
| options.colorScheme = colorScheme; | |
| if (contrast !== void 0) | |
| options.contrast = contrast; | |
| if (deviceScaleFactor !== void 0) | |
| options.deviceScaleFactor = deviceScaleFactor; | |
| if (extraHTTPHeaders !== void 0) | |
| options.extraHTTPHeaders = extraHTTPHeaders; | |
| if (forcedColors !== void 0) | |
| options.forcedColors = forcedColors; | |
| if (geolocation !== void 0) | |
| options.geolocation = geolocation; | |
| if (hasTouch !== void 0) | |
| options.hasTouch = hasTouch; | |
| if (httpCredentials !== void 0) | |
| options.httpCredentials = httpCredentials; | |
| if (ignoreHTTPSErrors !== void 0) | |
| options.ignoreHTTPSErrors = ignoreHTTPSErrors; | |
| if (isMobile !== void 0) | |
| options.isMobile = isMobile; | |
| if (javaScriptEnabled !== void 0) | |
| options.javaScriptEnabled = javaScriptEnabled; | |
| if (locale !== void 0) | |
| options.locale = locale; | |
| if (offline !== void 0) | |
| options.offline = offline; | |
| if (permissions !== void 0) | |
| options.permissions = permissions; | |
| if (proxy !== void 0) | |
| options.proxy = proxy; | |
| if (reducedMotion !== void 0) | |
| options.reducedMotion = reducedMotion; | |
| if (storageState !== void 0) | |
| options.storageState = storageState; | |
| if (clientCertificates?.length) | |
| options.clientCertificates = resolveClientCerticates(clientCertificates); | |
| if (timezoneId !== void 0) | |
| options.timezoneId = timezoneId; | |
| if (userAgent !== void 0) | |
| options.userAgent = userAgent; | |
| if (viewport !== void 0) | |
| options.viewport = viewport; | |
| if (baseURL !== void 0) | |
| options.baseURL = baseURL; | |
| if (serviceWorkers !== void 0) | |
| options.serviceWorkers = serviceWorkers; | |
| await use({ | |
| ...contextOptions, | |
| ...options | |
| }); | |
| }, { scope: "test", box: true }], | |
| _setupContextOptions: [async ({ playwright, actionTimeout, navigationTimeout, testIdAttribute }, use, _testInfo) => { | |
| const testInfo = _testInfo; | |
| if (testIdAttribute) | |
| playwrightLibrary.selectors.setTestIdAttribute(testIdAttribute); | |
| testInfo.snapshotSuffix = process.platform; | |
| testInfo._onCustomMessageCallback = () => Promise.reject(new Error("Only tests that use default Playwright context or page fixture support test_debug")); | |
| if (debugMode() === "inspector") | |
| testInfo._setIgnoreTimeouts(true); | |
| playwright._defaultContextTimeout = actionTimeout || 0; | |
| playwright._defaultContextNavigationTimeout = navigationTimeout || 0; | |
| await use(); | |
| playwright._defaultContextTimeout = void 0; | |
| playwright._defaultContextNavigationTimeout = void 0; | |
| }, { auto: "all-hooks-included", title: "context configuration", box: true }], | |
| _contextFactory: [async ({ | |
| browser, | |
| video, | |
| _reuseContext, | |
| _combinedContextOptions | |
| /** mitigate dep-via-auto lack of traceability */ | |
| }, use, testInfo) => { | |
| const testInfoImpl = testInfo; | |
| const videoMode = normalizeVideoMode(video); | |
| const captureVideo = shouldCaptureVideo(videoMode, testInfo) && !_reuseContext; | |
| const contexts = /* @__PURE__ */ new Map(); | |
| let counter = 0; | |
| await use(async (options) => { | |
| const hook = testInfoImpl._currentHookType(); | |
| if (hook === "beforeAll" || hook === "afterAll") { | |
| throw new Error([ | |
| `"context" and "page" fixtures are not supported in "${hook}" since they are created on a per-test basis.`, | |
| `If you would like to reuse a single page between tests, create context manually with browser.newContext(). See https://aka.ms/playwright/reuse-page for details.`, | |
| `If you would like to configure your page before each test, do that in beforeEach hook instead.` | |
| ].join("\n")); | |
| } | |
| const show = typeof video === "string" ? void 0 : video.show; | |
| const videoOptions = captureVideo ? { | |
| recordVideo: { | |
| dir: tracing().artifactsDir(), | |
| size: typeof video === "string" ? void 0 : video.size, | |
| showActions: show?.actions | |
| } | |
| } : {}; | |
| const context = await browser.newContext({ ...videoOptions, ...options }); | |
| let closed = false; | |
| const close = async () => { | |
| if (closed) | |
| return; | |
| closed = true; | |
| const closeReason = testInfo.status === "timedOut" ? "Test timeout of " + testInfo.timeout + "ms exceeded." : "Test ended."; | |
| await context.close({ reason: closeReason }); | |
| const preserveVideo = captureVideo && shouldPreserveVideo(videoMode, testInfo); | |
| if (preserveVideo) { | |
| const { pagesWithVideo: pagesForVideo } = contexts.get(context); | |
| const videos = pagesForVideo.map((p) => p.video()).filter((video2) => !!video2); | |
| await Promise.all(videos.map(async (v) => { | |
| try { | |
| const savedPath = testInfo.outputPath(`video${counter ? "-" + counter : ""}.webm`); | |
| ++counter; | |
| await v.saveAs(savedPath); | |
| testInfo.attachments.push({ name: "video", path: savedPath, contentType: "video/webm" }); | |
| } catch (e) { | |
| } | |
| })); | |
| } | |
| }; | |
| const contextData = { close, pagesWithVideo: [] }; | |
| if (captureVideo) | |
| context.on("page", (page) => contextData.pagesWithVideo.push(page)); | |
| contexts.set(context, contextData); | |
| return { context, close }; | |
| }); | |
| await Promise.all([...contexts.values()].map((data) => data.close())); | |
| }, { scope: "test", title: "context", box: true }], | |
| _optionContextReuseMode: ["none", { scope: "worker", option: true, box: true }], | |
| _optionConnectOptions: [void 0, { scope: "worker", option: true, box: true }], | |
| reuseContext: [false, { scope: "worker", option: true, box: true }], | |
| _reuseContext: [async ({ video, _optionContextReuseMode, reuseContext }, use) => { | |
| let mode = _optionContextReuseMode; | |
| if (process.env.PW_TEST_REUSE_CONTEXT || reuseContext) | |
| mode = "when-possible"; | |
| const reuse = mode === "when-possible" && normalizeVideoMode(video) === "off"; | |
| await use(reuse); | |
| }, { scope: "worker", title: "context", box: true }], | |
| context: async ({ browser, video, _reuseContext, _contextFactory }, use, testInfoPublic) => { | |
| const browserImpl = browser; | |
| const testInfo = testInfoPublic; | |
| const show = typeof video === "string" ? void 0 : video.show; | |
| attachConnectedHeaderIfNeeded(testInfo, browserImpl); | |
| if (!_reuseContext) { | |
| const { context: context2, close } = await _contextFactory(); | |
| await installScreencastTitleUpdater(testInfo, context2, show?.test); | |
| await use(context2); | |
| await close(); | |
| return; | |
| } | |
| const context = await browserImpl._wrapApiCall(() => browserImpl._newContextForReuse(), { internal: true }); | |
| await installScreencastTitleUpdater(testInfo, context, show?.test); | |
| await use(context); | |
| const closeReason = testInfo.status === "timedOut" ? "Test timeout of " + testInfo.timeout + "ms exceeded." : "Test ended."; | |
| await browserImpl._wrapApiCall(() => browserImpl._disconnectFromReusedContext(closeReason), { internal: true }); | |
| }, | |
| page: async ({ context, _reuseContext }, use) => { | |
| if (!_reuseContext) { | |
| await use(await context.newPage()); | |
| return; | |
| } | |
| let [page] = context.pages(); | |
| if (!page) | |
| page = await context.newPage(); | |
| await use(page); | |
| }, | |
| mount: async ({ page, baseURL }, use) => { | |
| const callMount = (params) => page.evaluate(async (p) => { | |
| const w = window; | |
| if (typeof w.mount !== "function") | |
| throw new Error("The gallery page does not define window.mount()."); | |
| await w.mount(p); | |
| }, params, { exposeFunctions: true }); | |
| await use(async (storyId, props) => { | |
| if (!baseURL) | |
| throw new Error("mount() requires `baseURL` to point at the component gallery. Set it in your Playwright config."); | |
| await page.goto(baseURL); | |
| await callMount({ story: storyId, props }); | |
| return Object.assign(page.locator("#root"), { | |
| // update() re-renders the same story with new props without navigating; if the gallery | |
| // reuses its root/instance, the framework reconciles and component state is preserved. | |
| update: (newProps) => callMount({ story: storyId, props: newProps }), | |
| unmount: () => page.evaluate(async () => { | |
| await window.unmount?.(); | |
| }) | |
| }); | |
| }); | |
| } | |
| }; | |
| function normalizeVideoMode(video) { | |
| if (!video) | |
| return "off"; | |
| let videoMode = typeof video === "string" ? video : video.mode; | |
| if (videoMode === "retry-with-video") | |
| videoMode = "on-first-retry"; | |
| return videoMode; | |
| } | |
| function shouldCaptureVideo(videoMode, testInfo) { | |
| return videoMode === "on" || videoMode === "retain-on-failure" || videoMode === "retain-on-failure-and-retries" || videoMode === "on-first-retry" && testInfo.retry === 1 || videoMode === "on-all-retries" && testInfo.retry > 0 || videoMode === "retain-on-first-failure" && testInfo.retry === 0; | |
| } | |
| function shouldPreserveVideo(videoMode, testInfo) { | |
| const testFailed = testInfo.status !== testInfo.expectedStatus; | |
| switch (videoMode) { | |
| case "on": | |
| case "on-first-retry": | |
| case "on-all-retries": | |
| return true; | |
| case "retain-on-failure": | |
| case "retain-on-first-failure": | |
| return testFailed; | |
| case "retain-on-failure-and-retries": | |
| return testFailed || testInfo.retry > 0; | |
| default: | |
| return false; | |
| } | |
| } | |
| function normalizeScreenshotMode(screenshot) { | |
| if (!screenshot) | |
| return "off"; | |
| return typeof screenshot === "string" ? screenshot : screenshot.mode; | |
| } | |
| function attachConnectedHeaderIfNeeded(testInfo, browser) { | |
| const connectHeaders = browser?._connection.headers; | |
| if (!connectHeaders) | |
| return; | |
| for (const header of connectHeaders) { | |
| if (header.name !== "x-playwright-attachment") | |
| continue; | |
| const [name, value] = header.value.split("="); | |
| if (!name || !value) | |
| continue; | |
| if (testInfo.attachments.some((attachment) => attachment.name === name)) | |
| continue; | |
| testInfo.attachments.push({ name, contentType: "text/plain", body: Buffer.from(value) }); | |
| } | |
| } | |
| function resolveFileToConfig(file) { | |
| const config2 = test.info().config.configFile; | |
| if (!config2 || !file) | |
| return file; | |
| if (import_path.default.isAbsolute(file)) | |
| return file; | |
| return import_path.default.resolve(import_path.default.dirname(config2), file); | |
| } | |
| function resolveClientCerticates(clientCertificates) { | |
| for (const cert of clientCertificates) { | |
| cert.certPath = resolveFileToConfig(cert.certPath); | |
| cert.keyPath = resolveFileToConfig(cert.keyPath); | |
| cert.pfxPath = resolveFileToConfig(cert.pfxPath); | |
| } | |
| return clientCertificates; | |
| } | |
| const kTracingStarted = /* @__PURE__ */ Symbol("kTracingStarted"); | |
| function connectOptionsFromEnv() { | |
| const wsEndpoint = process.env.PW_TEST_CONNECT_WS_ENDPOINT; | |
| if (!wsEndpoint) | |
| return void 0; | |
| const headers = process.env.PW_TEST_CONNECT_HEADERS ? JSON.parse(process.env.PW_TEST_CONNECT_HEADERS) : void 0; | |
| return { | |
| wsEndpoint, | |
| headers, | |
| exposeNetwork: process.env.PW_TEST_CONNECT_EXPOSE_NETWORK | |
| }; | |
| } | |
| class SnapshotRecorder { | |
| constructor(_artifactsRecorder, _mode, _name, _contentType, _extension, _doSnapshot) { | |
| this._artifactsRecorder = _artifactsRecorder; | |
| this._mode = _mode; | |
| this._name = _name; | |
| this._contentType = _contentType; | |
| this._extension = _extension; | |
| this._doSnapshot = _doSnapshot; | |
| this._ordinal = 0; | |
| this._temporary = []; | |
| } | |
| fixOrdinal() { | |
| this._ordinal = this.testInfo.attachments.filter((a) => a.name === this._name).length; | |
| } | |
| shouldCaptureUponFinish() { | |
| return this._mode === "on" || this._mode === "only-on-failure" && this.testInfo._isFailure() || this._mode === "on-first-failure" && this.testInfo._isFailure() && this.testInfo.retry === 0; | |
| } | |
| async maybeCapture() { | |
| if (!this.shouldCaptureUponFinish()) | |
| return; | |
| await Promise.all(this._artifactsRecorder._playwright._allPages().map((page) => this._snapshotPage(page, false))); | |
| } | |
| async persistTemporary() { | |
| if (this.shouldCaptureUponFinish()) { | |
| await Promise.all(this._temporary.map(async (file) => { | |
| try { | |
| const path2 = this._createAttachmentPath(); | |
| await import_fs.default.promises.rename(file, path2); | |
| this._attach(path2); | |
| } catch { | |
| } | |
| })); | |
| } | |
| } | |
| async captureTemporary(context) { | |
| if (this._mode === "on" || this._mode === "only-on-failure" || this._mode === "on-first-failure" && this.testInfo.retry === 0) | |
| await Promise.all(context.pages().map((page) => this._snapshotPage(page, true))); | |
| } | |
| _attach(screenshotPath) { | |
| this.testInfo.attachments.push({ name: this._name, path: screenshotPath, contentType: this._contentType }); | |
| } | |
| _createAttachmentPath() { | |
| const testFailed = this.testInfo._isFailure(); | |
| const index = this._ordinal + 1; | |
| ++this._ordinal; | |
| const path2 = this.testInfo.outputPath(`test-${testFailed ? "failed" : "finished"}-${index}${this._extension}`); | |
| return path2; | |
| } | |
| _createTemporaryArtifact(...name) { | |
| const file = import_path.default.join(this._artifactsRecorder._artifactsDir, ...name); | |
| return file; | |
| } | |
| async _snapshotPage(page, temporary) { | |
| if (page[this.testInfo._uniqueSymbol]) | |
| return; | |
| page[this.testInfo._uniqueSymbol] = true; | |
| try { | |
| const path2 = temporary ? this._createTemporaryArtifact(createGuid() + this._extension) : this._createAttachmentPath(); | |
| await this._doSnapshot(page, path2); | |
| if (temporary) | |
| this._temporary.push(path2); | |
| else | |
| this._attach(path2); | |
| } catch { | |
| } | |
| } | |
| get testInfo() { | |
| return this._artifactsRecorder._testInfo; | |
| } | |
| } | |
| class ArtifactsRecorder { | |
| constructor(playwright, artifactsDir, screenshot) { | |
| this._playwright = playwright; | |
| this._artifactsDir = artifactsDir; | |
| const screenshotOptions = typeof screenshot === "string" ? void 0 : screenshot; | |
| this._startedCollectingArtifacts = /* @__PURE__ */ Symbol("startedCollectingArtifacts"); | |
| this._screenshotRecorder = new SnapshotRecorder(this, normalizeScreenshotMode(screenshot), "screenshot", "image/png", ".png", async (page, path2) => { | |
| await page._wrapApiCall(async () => { | |
| await page.screenshot({ ...screenshotOptions, timeout: 5e3, path: path2, caret: "initial" }); | |
| }, { internal: true }); | |
| }); | |
| } | |
| async willStartTest(testInfo) { | |
| this._testInfo = testInfo; | |
| testInfo._onDidFinishTestFunctionCallbacks.add(() => this.didFinishTestFunction()); | |
| this._screenshotRecorder.fixOrdinal(); | |
| await Promise.all(this._playwright._allContexts().map((context) => this.didCreateBrowserContext(context))); | |
| const existingApiRequests = Array.from(this._playwright.request._contexts); | |
| await Promise.all(existingApiRequests.map((c) => this.didCreateRequestContext(c))); | |
| } | |
| async didCreateBrowserContext(context) { | |
| await this._startTraceChunkOnContextCreation(context, context.tracing); | |
| await this._startTraceChunkOnContextCreation(context.request, context.request.tracing); | |
| } | |
| async willCloseBrowserContext(context) { | |
| await this._stopTracing(context, context.tracing); | |
| await this._screenshotRecorder.captureTemporary(context); | |
| await this._takePageSnapshot(context); | |
| } | |
| async _takePageSnapshot(context) { | |
| if (process.env.PLAYWRIGHT_NO_COPY_PROMPT) | |
| return; | |
| if (this._testInfo.errors.length === 0) | |
| return; | |
| if (this._testInfo.errors.some((e) => e.errorContext)) | |
| return; | |
| if (this._pageSnapshot) | |
| return; | |
| const page = context.pages()[0]; | |
| if (!page) | |
| return; | |
| try { | |
| await page._wrapApiCall(async () => { | |
| this._pageSnapshot = await page.ariaSnapshot({ mode: "ai", timeout: 5e3 }); | |
| }, { internal: true }); | |
| } catch (error) { | |
| debugLogger.log("error", `failed to capture aria snapshot: ${error}`); | |
| } | |
| } | |
| async didCreateRequestContext(context) { | |
| await this._startTraceChunkOnContextCreation(context, context.tracing); | |
| } | |
| async willCloseRequestContext(context) { | |
| await this._stopTracing(context, context.tracing); | |
| } | |
| async didFinishTestFunction() { | |
| await this._screenshotRecorder.maybeCapture(); | |
| } | |
| async didFinishTest() { | |
| await this.didFinishTestFunction(); | |
| const leftoverContexts = this._playwright._allContexts(); | |
| const leftoverApiRequests = Array.from(this._playwright.request._contexts); | |
| await Promise.all(leftoverContexts.map(async (context2) => { | |
| await this._stopTracing(context2.request, context2.request.tracing); | |
| await this._stopTracing(context2, context2.tracing); | |
| }).concat(leftoverApiRequests.map(async (context2) => { | |
| await this._stopTracing(context2, context2.tracing); | |
| }))); | |
| await this._screenshotRecorder.persistTemporary(); | |
| const context = leftoverContexts[0]; | |
| if (context) | |
| await this._takePageSnapshot(context); | |
| if (this._testInfo.errors.length > 0) { | |
| const hasMatcherAriaSnapshot = this._testInfo.errors.some((e) => e.errorContext); | |
| const errorContextContent = (0, import_errorContext.buildErrorContext)({ | |
| titlePath: this._testInfo.titlePath, | |
| location: { file: this._testInfo.file, line: this._testInfo.line, column: this._testInfo.column }, | |
| errors: this._testInfo.errors, | |
| pageSnapshot: hasMatcherAriaSnapshot ? void 0 : this._pageSnapshot | |
| }); | |
| if (errorContextContent) { | |
| const filePath = this._testInfo.outputPath("error-context.md"); | |
| await import_fs.default.promises.writeFile(filePath, errorContextContent, "utf8"); | |
| this._testInfo._attach({ | |
| name: "error-context", | |
| contentType: "text/markdown", | |
| path: filePath | |
| }, void 0); | |
| } | |
| } | |
| } | |
| async _startTraceChunkOnContextCreation(channelOwner, tracing2) { | |
| await channelOwner._wrapApiCall(async () => { | |
| const options = this._testInfo._tracing.traceOptions(); | |
| if (options) { | |
| const title = this._testInfo._tracing.traceTitle(); | |
| const name = this._testInfo._tracing.generateNextTraceRecordingName(); | |
| if (!tracing2[kTracingStarted]) { | |
| await tracing2.start({ ...options, title, name }); | |
| tracing2[kTracingStarted] = true; | |
| } else { | |
| await tracing2.startChunk({ title, name }); | |
| } | |
| } else { | |
| if (tracing2[kTracingStarted]) { | |
| tracing2[kTracingStarted] = false; | |
| await tracing2.stop(); | |
| } | |
| } | |
| }, { internal: true }); | |
| } | |
| async _stopTracing(channelOwner, tracing2) { | |
| await channelOwner._wrapApiCall(async () => { | |
| if (tracing2[this._startedCollectingArtifacts]) | |
| return; | |
| tracing2[this._startedCollectingArtifacts] = true; | |
| if (this._testInfo._tracing.traceOptions() && tracing2[kTracingStarted]) | |
| await tracing2.stopChunk({ path: this._testInfo._tracing.maybeGenerateNextTraceRecordingPath() }); | |
| }, { internal: true }); | |
| } | |
| } | |
| async function installScreencastTitleUpdater(testInfo, context, testAnnotate) { | |
| if (!testAnnotate) | |
| return; | |
| const testTitle = testAnnotate.level === "file" ? [testInfo.titlePath[0]] : testInfo.titlePath; | |
| const stepStack = []; | |
| const overlays = /* @__PURE__ */ new Map(); | |
| const position = testAnnotate.position ?? "top-left"; | |
| const fontSize = testAnnotate.fontSize ?? 14; | |
| const level = testAnnotate.level ?? "step"; | |
| const updateOverlay = async () => { | |
| const parts = level === "step" ? [...testTitle, ...stepStack] : testTitle; | |
| const html = createTestOverlay(parts, position, fontSize); | |
| for (const page of context.pages()) { | |
| await overlays.get(page)?.dispose(); | |
| overlays.delete(page); | |
| const disposable = await page.screencast.showOverlay(html); | |
| overlays.set(page, disposable); | |
| } | |
| }; | |
| testInfo._onUserStepBegin = async (title) => { | |
| stepStack.push(title); | |
| await updateOverlay(); | |
| }; | |
| testInfo._onUserStepEnd = async () => { | |
| stepStack.pop(); | |
| await updateOverlay(); | |
| }; | |
| context.on("page", async () => { | |
| void updateOverlay(); | |
| }); | |
| await updateOverlay(); | |
| } | |
| function createTestOverlay(parts, position, fontSize) { | |
| const positionStyles = { | |
| "top-left": "top: 6px; left: 6px;", | |
| "top": "top: 6px; left: 50%; transform: translateX(-50%);", | |
| "top-right": "top: 6px; right: 6px;", | |
| "bottom-left": "bottom: 6px; left: 6px;", | |
| "bottom": "bottom: 6px; left: 50%; transform: translateX(-50%);", | |
| "bottom-right": "bottom: 6px; right: 6px;" | |
| }; | |
| const posStyle = positionStyles[position] ?? positionStyles["top-left"]; | |
| return `<div style="white-space: nowrap; font-size: ${fontSize}px; padding: 3px 6px; background: rgba(0,0,0,0.5); color: white; border-radius: 4px; position: absolute; ${posStyle}"> | |
| ${parts.map((p) => `<div>${escapeHTML(p)}</div>`).join("")} | |
| </div>`; | |
| } | |
| function renderTitle(type, method, params, title) { | |
| return renderTitleForCall({ title, type, method, params }); | |
| } | |
| function renderSubtitle(type, method, params) { | |
| const subtitle = renderSubtitleForCall({ type, method, params }); | |
| return subtitle === void 0 ? void 0 : truncateParam(subtitle); | |
| } | |
| function tracing() { | |
| return test.info()._tracing; | |
| } | |
| const test = _utilityTest.extend(playwrightFixtures); | |
| // Annotate the CommonJS export names for ESM import in node: | |
| 0 && (module.exports = { | |
| _baseTest, | |
| _utilityTest, | |
| defineConfig, | |
| expect, | |
| mergeExpects, | |
| mergeTests, | |
| test | |
| }); | |