@one2x/playwright 1.57.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +5 -0
- package/README.md +168 -0
- package/ThirdPartyNotices.txt +6277 -0
- package/cli.js +19 -0
- package/index.d.ts +17 -0
- package/index.js +17 -0
- package/index.mjs +18 -0
- package/jsx-runtime.js +42 -0
- package/jsx-runtime.mjs +21 -0
- package/lib/agents/copilot-setup-steps.yml +34 -0
- package/lib/agents/generateAgents.js +394 -0
- package/lib/agents/generateAgents.js.map +7 -0
- package/lib/agents/playwright-test-coverage.prompt.md +31 -0
- package/lib/agents/playwright-test-generate.prompt.md +8 -0
- package/lib/agents/playwright-test-generator.agent.md +88 -0
- package/lib/agents/playwright-test-heal.prompt.md +6 -0
- package/lib/agents/playwright-test-healer.agent.md +55 -0
- package/lib/agents/playwright-test-plan.prompt.md +9 -0
- package/lib/agents/playwright-test-planner.agent.md +117 -0
- package/lib/common/config.js +280 -0
- package/lib/common/config.js.map +7 -0
- package/lib/common/configLoader.js +344 -0
- package/lib/common/configLoader.js.map +7 -0
- package/lib/common/esmLoaderHost.js +102 -0
- package/lib/common/esmLoaderHost.js.map +7 -0
- package/lib/common/expectBundle.js +52 -0
- package/lib/common/expectBundle.js.map +7 -0
- package/lib/common/expectBundleImpl.js +389 -0
- package/lib/common/expectBundleImpl.js.map +7 -0
- package/lib/common/fixtures.js +302 -0
- package/lib/common/fixtures.js.map +7 -0
- package/lib/common/globals.js +58 -0
- package/lib/common/globals.js.map +7 -0
- package/lib/common/ipc.js +60 -0
- package/lib/common/ipc.js.map +7 -0
- package/lib/common/poolBuilder.js +85 -0
- package/lib/common/poolBuilder.js.map +7 -0
- package/lib/common/process.js +104 -0
- package/lib/common/process.js.map +7 -0
- package/lib/common/suiteUtils.js +140 -0
- package/lib/common/suiteUtils.js.map +7 -0
- package/lib/common/test.js +321 -0
- package/lib/common/test.js.map +7 -0
- package/lib/common/testLoader.js +101 -0
- package/lib/common/testLoader.js.map +7 -0
- package/lib/common/testType.js +298 -0
- package/lib/common/testType.js.map +7 -0
- package/lib/common/validators.js +68 -0
- package/lib/common/validators.js.map +7 -0
- package/lib/fsWatcher.js +67 -0
- package/lib/fsWatcher.js.map +7 -0
- package/lib/index.js +682 -0
- package/lib/index.js.map +7 -0
- package/lib/internalsForTest.js +42 -0
- package/lib/internalsForTest.js.map +7 -0
- package/lib/isomorphic/events.js +77 -0
- package/lib/isomorphic/events.js.map +7 -0
- package/lib/isomorphic/folders.js +30 -0
- package/lib/isomorphic/folders.js.map +7 -0
- package/lib/isomorphic/stringInternPool.js +69 -0
- package/lib/isomorphic/stringInternPool.js.map +7 -0
- package/lib/isomorphic/teleReceiver.js +508 -0
- package/lib/isomorphic/teleReceiver.js.map +7 -0
- package/lib/isomorphic/teleSuiteUpdater.js +137 -0
- package/lib/isomorphic/teleSuiteUpdater.js.map +7 -0
- package/lib/isomorphic/testServerConnection.js +211 -0
- package/lib/isomorphic/testServerConnection.js.map +7 -0
- package/lib/isomorphic/testServerInterface.js +16 -0
- package/lib/isomorphic/testServerInterface.js.map +7 -0
- package/lib/isomorphic/testTree.js +334 -0
- package/lib/isomorphic/testTree.js.map +7 -0
- package/lib/isomorphic/types.d.js +16 -0
- package/lib/isomorphic/types.d.js.map +7 -0
- package/lib/loader/loaderMain.js +59 -0
- package/lib/loader/loaderMain.js.map +7 -0
- package/lib/matchers/expect.js +325 -0
- package/lib/matchers/expect.js.map +7 -0
- package/lib/matchers/matcherHint.js +87 -0
- package/lib/matchers/matcherHint.js.map +7 -0
- package/lib/matchers/matchers.js +366 -0
- package/lib/matchers/matchers.js.map +7 -0
- package/lib/matchers/toBeTruthy.js +73 -0
- package/lib/matchers/toBeTruthy.js.map +7 -0
- package/lib/matchers/toEqual.js +99 -0
- package/lib/matchers/toEqual.js.map +7 -0
- package/lib/matchers/toHaveURL.js +102 -0
- package/lib/matchers/toHaveURL.js.map +7 -0
- package/lib/matchers/toMatchAriaSnapshot.js +159 -0
- package/lib/matchers/toMatchAriaSnapshot.js.map +7 -0
- package/lib/matchers/toMatchSnapshot.js +341 -0
- package/lib/matchers/toMatchSnapshot.js.map +7 -0
- package/lib/matchers/toMatchText.js +99 -0
- package/lib/matchers/toMatchText.js.map +7 -0
- package/lib/mcp/browser/actions.d.js +16 -0
- package/lib/mcp/browser/actions.d.js.map +7 -0
- package/lib/mcp/browser/browserContextFactory.js +357 -0
- package/lib/mcp/browser/browserContextFactory.js.map +7 -0
- package/lib/mcp/browser/browserServerBackend.js +76 -0
- package/lib/mcp/browser/browserServerBackend.js.map +7 -0
- package/lib/mcp/browser/codegen.js +66 -0
- package/lib/mcp/browser/codegen.js.map +7 -0
- package/lib/mcp/browser/config.js +425 -0
- package/lib/mcp/browser/config.js.map +7 -0
- package/lib/mcp/browser/context.js +287 -0
- package/lib/mcp/browser/context.js.map +7 -0
- package/lib/mcp/browser/response.js +228 -0
- package/lib/mcp/browser/response.js.map +7 -0
- package/lib/mcp/browser/sessionLog.js +160 -0
- package/lib/mcp/browser/sessionLog.js.map +7 -0
- package/lib/mcp/browser/tab.js +280 -0
- package/lib/mcp/browser/tab.js.map +7 -0
- package/lib/mcp/browser/tools/actionRetry.js +40 -0
- package/lib/mcp/browser/tools/actionRetry.js.map +7 -0
- package/lib/mcp/browser/tools/common.js +63 -0
- package/lib/mcp/browser/tools/common.js.map +7 -0
- package/lib/mcp/browser/tools/console.js +44 -0
- package/lib/mcp/browser/tools/console.js.map +7 -0
- package/lib/mcp/browser/tools/dialogs.js +60 -0
- package/lib/mcp/browser/tools/dialogs.js.map +7 -0
- package/lib/mcp/browser/tools/evaluate.js +69 -0
- package/lib/mcp/browser/tools/evaluate.js.map +7 -0
- package/lib/mcp/browser/tools/files.js +58 -0
- package/lib/mcp/browser/tools/files.js.map +7 -0
- package/lib/mcp/browser/tools/form.js +79 -0
- package/lib/mcp/browser/tools/form.js.map +7 -0
- package/lib/mcp/browser/tools/install.js +69 -0
- package/lib/mcp/browser/tools/install.js.map +7 -0
- package/lib/mcp/browser/tools/keyboard.js +84 -0
- package/lib/mcp/browser/tools/keyboard.js.map +7 -0
- package/lib/mcp/browser/tools/mouse.js +107 -0
- package/lib/mcp/browser/tools/mouse.js.map +7 -0
- package/lib/mcp/browser/tools/navigate.js +62 -0
- package/lib/mcp/browser/tools/navigate.js.map +7 -0
- package/lib/mcp/browser/tools/network.js +54 -0
- package/lib/mcp/browser/tools/network.js.map +7 -0
- package/lib/mcp/browser/tools/pdf.js +59 -0
- package/lib/mcp/browser/tools/pdf.js.map +7 -0
- package/lib/mcp/browser/tools/screenshot.js +106 -0
- package/lib/mcp/browser/tools/screenshot.js.map +7 -0
- package/lib/mcp/browser/tools/snapshot.js +312 -0
- package/lib/mcp/browser/tools/snapshot.js.map +7 -0
- package/lib/mcp/browser/tools/tabs.js +67 -0
- package/lib/mcp/browser/tools/tabs.js.map +7 -0
- package/lib/mcp/browser/tools/tool.js +49 -0
- package/lib/mcp/browser/tools/tool.js.map +7 -0
- package/lib/mcp/browser/tools/tracing.js +74 -0
- package/lib/mcp/browser/tools/tracing.js.map +7 -0
- package/lib/mcp/browser/tools/utils.js +96 -0
- package/lib/mcp/browser/tools/utils.js.map +7 -0
- package/lib/mcp/browser/tools/verify.js +153 -0
- package/lib/mcp/browser/tools/verify.js.map +7 -0
- package/lib/mcp/browser/tools/wait.js +63 -0
- package/lib/mcp/browser/tools/wait.js.map +7 -0
- package/lib/mcp/browser/tools.js +80 -0
- package/lib/mcp/browser/tools.js.map +7 -0
- package/lib/mcp/browser/watchdog.js +44 -0
- package/lib/mcp/browser/watchdog.js.map +7 -0
- package/lib/mcp/config.d.js +16 -0
- package/lib/mcp/config.d.js.map +7 -0
- package/lib/mcp/extension/cdpRelay.js +351 -0
- package/lib/mcp/extension/cdpRelay.js.map +7 -0
- package/lib/mcp/extension/extensionContextFactory.js +75 -0
- package/lib/mcp/extension/extensionContextFactory.js.map +7 -0
- package/lib/mcp/extension/protocol.js +28 -0
- package/lib/mcp/extension/protocol.js.map +7 -0
- package/lib/mcp/index.js +61 -0
- package/lib/mcp/index.js.map +7 -0
- package/lib/mcp/log.js +35 -0
- package/lib/mcp/log.js.map +7 -0
- package/lib/mcp/program.js +118 -0
- package/lib/mcp/program.js.map +7 -0
- package/lib/mcp/sdk/bundle.js +81 -0
- package/lib/mcp/sdk/bundle.js.map +7 -0
- package/lib/mcp/sdk/exports.js +32 -0
- package/lib/mcp/sdk/exports.js.map +7 -0
- package/lib/mcp/sdk/http.js +276 -0
- package/lib/mcp/sdk/http.js.map +7 -0
- package/lib/mcp/sdk/inProcessTransport.js +71 -0
- package/lib/mcp/sdk/inProcessTransport.js.map +7 -0
- package/lib/mcp/sdk/mdb.js +208 -0
- package/lib/mcp/sdk/mdb.js.map +7 -0
- package/lib/mcp/sdk/proxyBackend.js +128 -0
- package/lib/mcp/sdk/proxyBackend.js.map +7 -0
- package/lib/mcp/sdk/server.js +190 -0
- package/lib/mcp/sdk/server.js.map +7 -0
- package/lib/mcp/sdk/tool.js +51 -0
- package/lib/mcp/sdk/tool.js.map +7 -0
- package/lib/mcp/test/browserBackend.js +98 -0
- package/lib/mcp/test/browserBackend.js.map +7 -0
- package/lib/mcp/test/generatorTools.js +122 -0
- package/lib/mcp/test/generatorTools.js.map +7 -0
- package/lib/mcp/test/plannerTools.js +46 -0
- package/lib/mcp/test/plannerTools.js.map +7 -0
- package/lib/mcp/test/seed.js +82 -0
- package/lib/mcp/test/seed.js.map +7 -0
- package/lib/mcp/test/streams.js +41 -0
- package/lib/mcp/test/streams.js.map +7 -0
- package/lib/mcp/test/testBackend.js +97 -0
- package/lib/mcp/test/testBackend.js.map +7 -0
- package/lib/mcp/test/testContext.js +216 -0
- package/lib/mcp/test/testContext.js.map +7 -0
- package/lib/mcp/test/testTool.js +30 -0
- package/lib/mcp/test/testTool.js.map +7 -0
- package/lib/mcp/test/testTools.js +111 -0
- package/lib/mcp/test/testTools.js.map +7 -0
- package/lib/mcpBundleImpl.js +41 -0
- package/lib/mcpBundleImpl.js.map +7 -0
- package/lib/plugins/gitCommitInfoPlugin.js +198 -0
- package/lib/plugins/gitCommitInfoPlugin.js.map +7 -0
- package/lib/plugins/index.js +28 -0
- package/lib/plugins/index.js.map +7 -0
- package/lib/plugins/webServerPlugin.js +233 -0
- package/lib/plugins/webServerPlugin.js.map +7 -0
- package/lib/program.js +412 -0
- package/lib/program.js.map +7 -0
- package/lib/reporters/base.js +609 -0
- package/lib/reporters/base.js.map +7 -0
- package/lib/reporters/blob.js +135 -0
- package/lib/reporters/blob.js.map +7 -0
- package/lib/reporters/dot.js +82 -0
- package/lib/reporters/dot.js.map +7 -0
- package/lib/reporters/empty.js +32 -0
- package/lib/reporters/empty.js.map +7 -0
- package/lib/reporters/github.js +128 -0
- package/lib/reporters/github.js.map +7 -0
- package/lib/reporters/html.js +623 -0
- package/lib/reporters/html.js.map +7 -0
- package/lib/reporters/internalReporter.js +130 -0
- package/lib/reporters/internalReporter.js.map +7 -0
- package/lib/reporters/json.js +254 -0
- package/lib/reporters/json.js.map +7 -0
- package/lib/reporters/junit.js +232 -0
- package/lib/reporters/junit.js.map +7 -0
- package/lib/reporters/line.js +113 -0
- package/lib/reporters/line.js.map +7 -0
- package/lib/reporters/list.js +231 -0
- package/lib/reporters/list.js.map +7 -0
- package/lib/reporters/listModeReporter.js +69 -0
- package/lib/reporters/listModeReporter.js.map +7 -0
- package/lib/reporters/markdown.js +144 -0
- package/lib/reporters/markdown.js.map +7 -0
- package/lib/reporters/merge.js +541 -0
- package/lib/reporters/merge.js.map +7 -0
- package/lib/reporters/multiplexer.js +104 -0
- package/lib/reporters/multiplexer.js.map +7 -0
- package/lib/reporters/reporterV2.js +102 -0
- package/lib/reporters/reporterV2.js.map +7 -0
- package/lib/reporters/teleEmitter.js +298 -0
- package/lib/reporters/teleEmitter.js.map +7 -0
- package/lib/reporters/versions/blobV1.js +16 -0
- package/lib/reporters/versions/blobV1.js.map +7 -0
- package/lib/runner/dispatcher.js +491 -0
- package/lib/runner/dispatcher.js.map +7 -0
- package/lib/runner/failureTracker.js +72 -0
- package/lib/runner/failureTracker.js.map +7 -0
- package/lib/runner/lastRun.js +77 -0
- package/lib/runner/lastRun.js.map +7 -0
- package/lib/runner/loadUtils.js +334 -0
- package/lib/runner/loadUtils.js.map +7 -0
- package/lib/runner/loaderHost.js +89 -0
- package/lib/runner/loaderHost.js.map +7 -0
- package/lib/runner/processHost.js +161 -0
- package/lib/runner/processHost.js.map +7 -0
- package/lib/runner/projectUtils.js +241 -0
- package/lib/runner/projectUtils.js.map +7 -0
- package/lib/runner/rebase.js +189 -0
- package/lib/runner/rebase.js.map +7 -0
- package/lib/runner/reporters.js +138 -0
- package/lib/runner/reporters.js.map +7 -0
- package/lib/runner/runner.js +110 -0
- package/lib/runner/sigIntWatcher.js +96 -0
- package/lib/runner/sigIntWatcher.js.map +7 -0
- package/lib/runner/taskRunner.js +127 -0
- package/lib/runner/taskRunner.js.map +7 -0
- package/lib/runner/tasks.js +410 -0
- package/lib/runner/tasks.js.map +7 -0
- package/lib/runner/testGroups.js +117 -0
- package/lib/runner/testGroups.js.map +7 -0
- package/lib/runner/testRunner.js +390 -0
- package/lib/runner/testRunner.js.map +7 -0
- package/lib/runner/testServer.js +267 -0
- package/lib/runner/testServer.js.map +7 -0
- package/lib/runner/uiModeReporter.js +30 -0
- package/lib/runner/uiModeReporter.js.map +7 -0
- package/lib/runner/vcs.js +72 -0
- package/lib/runner/vcs.js.map +7 -0
- package/lib/runner/watchMode.js +395 -0
- package/lib/runner/watchMode.js.map +7 -0
- package/lib/runner/workerHost.js +95 -0
- package/lib/runner/workerHost.js.map +7 -0
- package/lib/third_party/pirates.js +62 -0
- package/lib/third_party/pirates.js.map +7 -0
- package/lib/third_party/tsconfig-loader.js +103 -0
- package/lib/third_party/tsconfig-loader.js.map +7 -0
- package/lib/transform/babelBundle.js +43 -0
- package/lib/transform/babelBundle.js.map +7 -0
- package/lib/transform/babelBundleImpl.js +461 -0
- package/lib/transform/babelBundleImpl.js.map +7 -0
- package/lib/transform/compilationCache.js +272 -0
- package/lib/transform/compilationCache.js.map +7 -0
- package/lib/transform/esmLoader.js +104 -0
- package/lib/transform/esmLoader.js.map +7 -0
- package/lib/transform/portTransport.js +67 -0
- package/lib/transform/portTransport.js.map +7 -0
- package/lib/transform/transform.js +293 -0
- package/lib/transform/transform.js.map +7 -0
- package/lib/util.js +403 -0
- package/lib/util.js.map +7 -0
- package/lib/utilsBundle.js +43 -0
- package/lib/utilsBundle.js.map +7 -0
- package/lib/utilsBundleImpl.js +100 -0
- package/lib/utilsBundleImpl.js.map +7 -0
- package/lib/worker/fixtureRunner.js +258 -0
- package/lib/worker/fixtureRunner.js.map +7 -0
- package/lib/worker/testInfo.js +514 -0
- package/lib/worker/testInfo.js.map +7 -0
- package/lib/worker/testTracing.js +344 -0
- package/lib/worker/testTracing.js.map +7 -0
- package/lib/worker/timeoutManager.js +174 -0
- package/lib/worker/timeoutManager.js.map +7 -0
- package/lib/worker/util.js +31 -0
- package/lib/worker/util.js.map +7 -0
- package/lib/worker/workerMain.js +520 -0
- package/lib/worker/workerMain.js.map +7 -0
- package/package.json +74 -0
- package/test.d.ts +18 -0
- package/test.js +24 -0
- package/test.mjs +33 -0
- package/types/test.d.ts +10196 -0
- package/types/testReporter.d.ts +821 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/matchers/toMatchSnapshot.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright Microsoft Corporation. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport fs from 'fs';\nimport path from 'path';\n\nimport { compareBuffersOrStrings, getComparator, isString } from 'playwright-core/lib/utils';\nimport { colors } from 'playwright-core/lib/utils';\nimport { mime } from 'playwright-core/lib/utilsBundle';\n\nimport { addSuffixToFilePath, expectTypes } from '../util';\nimport { callLogText, formatMatcherMessage } from './matcherHint';\nimport { currentTestInfo } from '../common/globals';\n\nimport type { MatcherResult } from './matcherHint';\nimport type { ExpectMatcherStateInternal } from './matchers';\nimport type { FullProjectInternal } from '../common/config';\nimport type { TestInfoImpl, TestStepInfoImpl } from '../worker/testInfo';\nimport type { Locator, Page } from 'playwright-core';\nimport type { ExpectScreenshotOptions, Page as PageEx } from 'playwright-core/lib/client/page';\nimport type { Comparator, ImageComparatorOptions } from 'playwright-core/lib/utils';\n\ntype NameOrSegments = string | string[];\n\ntype ImageMatcherResult = MatcherResult<string, string> & { diff?: string };\n\ntype ToHaveScreenshotConfigOptions = NonNullable<NonNullable<FullProjectInternal['expect']>['toHaveScreenshot']> & {\n _comparator?: string;\n};\n\ntype ToHaveScreenshotOptions = ToHaveScreenshotConfigOptions & {\n clip?: {\n x: number;\n y: number;\n width: number;\n height: number;\n };\n fullPage?: boolean;\n mask?: Array<Locator>;\n maskColor?: string;\n omitBackground?: boolean;\n timeout?: number;\n};\n\n// Keep in sync with above (begin).\nconst NonConfigProperties: (keyof ToHaveScreenshotOptions)[] = [\n 'clip',\n 'fullPage',\n 'mask',\n 'maskColor',\n 'omitBackground',\n 'timeout',\n];\n// Keep in sync with above (end).\n\nclass SnapshotHelper {\n readonly testInfo: TestInfoImpl;\n readonly name: string;\n readonly attachmentBaseName: string;\n readonly legacyExpectedPath: string;\n readonly previousPath: string;\n readonly expectedPath: string;\n readonly actualPath: string;\n readonly diffPath: string;\n readonly mimeType: string;\n readonly kind: 'Screenshot'|'Snapshot';\n readonly updateSnapshots: 'all' | 'changed' | 'missing' | 'none';\n readonly comparator: Comparator;\n readonly options: Omit<ToHaveScreenshotOptions, '_comparator'> & { comparator?: string };\n readonly matcherName: string;\n readonly locator: Locator | undefined;\n\n constructor(\n testInfo: TestInfoImpl,\n matcherName: 'toMatchSnapshot' | 'toHaveScreenshot',\n locator: Locator | undefined,\n anonymousSnapshotExtension: string | undefined,\n configOptions: ToHaveScreenshotConfigOptions,\n nameOrOptions: NameOrSegments | { name?: NameOrSegments } & ToHaveScreenshotOptions,\n optOptions: ToHaveScreenshotOptions,\n ) {\n let name: NameOrSegments | undefined;\n if (Array.isArray(nameOrOptions) || typeof nameOrOptions === 'string') {\n name = nameOrOptions;\n this.options = { ...optOptions };\n } else {\n const { name: nameFromOptions, ...options } = nameOrOptions;\n this.options = options;\n name = nameFromOptions;\n }\n\n this.name = Array.isArray(name) ? name.join(path.sep) : name || '';\n const resolvedPaths = testInfo._resolveSnapshotPaths(matcherName === 'toHaveScreenshot' ? 'screenshot' : 'snapshot', name, 'updateSnapshotIndex', anonymousSnapshotExtension);\n this.expectedPath = resolvedPaths.absoluteSnapshotPath;\n this.attachmentBaseName = resolvedPaths.relativeOutputPath;\n\n const outputBasePath = testInfo._getOutputPath(resolvedPaths.relativeOutputPath);\n this.legacyExpectedPath = addSuffixToFilePath(outputBasePath, '-expected');\n this.previousPath = addSuffixToFilePath(outputBasePath, '-previous');\n this.actualPath = addSuffixToFilePath(outputBasePath, '-actual');\n this.diffPath = addSuffixToFilePath(outputBasePath, '-diff');\n\n const filteredConfigOptions = { ...configOptions };\n for (const prop of NonConfigProperties)\n delete (filteredConfigOptions as any)[prop];\n this.options = {\n ...filteredConfigOptions,\n ...this.options,\n };\n\n // While comparator is not a part of the public API, it is translated here.\n if ((this.options as any)._comparator) {\n this.options.comparator = (this.options as any)._comparator;\n delete (this.options as any)._comparator;\n }\n\n if (this.options.maxDiffPixels !== undefined && this.options.maxDiffPixels < 0)\n throw new Error('`maxDiffPixels` option value must be non-negative integer');\n\n if (this.options.maxDiffPixelRatio !== undefined && (this.options.maxDiffPixelRatio < 0 || this.options.maxDiffPixelRatio > 1))\n throw new Error('`maxDiffPixelRatio` option value must be between 0 and 1');\n\n this.matcherName = matcherName;\n this.locator = locator;\n\n this.updateSnapshots = testInfo.config.updateSnapshots;\n this.mimeType = mime.getType(path.basename(this.expectedPath)) ?? 'application/octet-stream';\n this.comparator = getComparator(this.mimeType);\n\n this.testInfo = testInfo;\n this.kind = this.mimeType.startsWith('image/') ? 'Screenshot' : 'Snapshot';\n }\n\n createMatcherResult(message: string, pass: boolean, log?: string[]): ImageMatcherResult {\n const unfiltered: ImageMatcherResult = {\n name: this.matcherName,\n expected: this.expectedPath,\n actual: this.actualPath,\n diff: this.diffPath,\n pass,\n message: () => message,\n log,\n };\n return Object.fromEntries(Object.entries(unfiltered).filter(([_, v]) => v !== undefined)) as ImageMatcherResult;\n }\n\n handleMissingNegated(): ImageMatcherResult {\n const isWriteMissingMode = this.updateSnapshots !== 'none';\n const message = `A snapshot doesn't exist at ${this.expectedPath}${isWriteMissingMode ? ', matchers using \".not\" won\\'t write them automatically.' : '.'}`;\n // NOTE: 'isNot' matcher implies inversed value.\n return this.createMatcherResult(message, true);\n }\n\n handleDifferentNegated(): ImageMatcherResult {\n // NOTE: 'isNot' matcher implies inversed value.\n return this.createMatcherResult('', false);\n }\n\n handleMatchingNegated(): ImageMatcherResult {\n const message = [\n colors.red(`${this.kind} comparison failed:`),\n '',\n indent('Expected result should be different from the actual one.', ' '),\n ].join('\\n');\n // NOTE: 'isNot' matcher implies inversed value.\n return this.createMatcherResult(message, true);\n }\n\n handleMissing(actual: Buffer | string, step: TestStepInfoImpl | undefined): ImageMatcherResult {\n const isWriteMissingMode = this.updateSnapshots !== 'none';\n if (isWriteMissingMode)\n writeFileSync(this.expectedPath, actual);\n step?._attachToStep({ name: addSuffixToFilePath(this.attachmentBaseName, '-expected'), contentType: this.mimeType, path: this.expectedPath });\n writeFileSync(this.actualPath, actual);\n step?._attachToStep({ name: addSuffixToFilePath(this.attachmentBaseName, '-actual'), contentType: this.mimeType, path: this.actualPath });\n const message = `A snapshot doesn't exist at ${this.expectedPath}${isWriteMissingMode ? ', writing actual.' : '.'}`;\n if (this.updateSnapshots === 'all' || this.updateSnapshots === 'changed') {\n /* eslint-disable no-console */\n console.log(message);\n return this.createMatcherResult(message, true);\n }\n if (this.updateSnapshots === 'missing') {\n this.testInfo._hasNonRetriableError = true;\n this.testInfo._failWithError(new Error(message));\n return this.createMatcherResult('', true);\n }\n return this.createMatcherResult(message, false);\n }\n\n handleDifferent(\n actual: Buffer | string | undefined,\n expected: Buffer | string | undefined,\n previous: Buffer | string | undefined,\n diff: Buffer | string | undefined,\n header: string,\n diffError: string,\n log: string[] | undefined,\n step: TestStepInfoImpl | undefined): ImageMatcherResult {\n const output = [`${header}${indent(diffError, ' ')}`];\n if (this.name) {\n output.push('');\n output.push(` Snapshot: ${this.name}`);\n }\n if (expected !== undefined) {\n // Copy the expectation inside the `test-results/` folder for backwards compatibility,\n // so that one can upload `test-results/` directory and have all the data inside.\n writeFileSync(this.legacyExpectedPath, expected);\n step?._attachToStep({ name: addSuffixToFilePath(this.attachmentBaseName, '-expected'), contentType: this.mimeType, path: this.expectedPath });\n }\n if (previous !== undefined) {\n writeFileSync(this.previousPath, previous);\n step?._attachToStep({ name: addSuffixToFilePath(this.attachmentBaseName, '-previous'), contentType: this.mimeType, path: this.previousPath });\n }\n if (actual !== undefined) {\n writeFileSync(this.actualPath, actual);\n step?._attachToStep({ name: addSuffixToFilePath(this.attachmentBaseName, '-actual'), contentType: this.mimeType, path: this.actualPath });\n }\n if (diff !== undefined) {\n writeFileSync(this.diffPath, diff);\n step?._attachToStep({ name: addSuffixToFilePath(this.attachmentBaseName, '-diff'), contentType: this.mimeType, path: this.diffPath });\n }\n\n if (log?.length)\n output.push(callLogText(log));\n else\n output.push('');\n\n return this.createMatcherResult(output.join('\\n'), false, log);\n }\n\n handleMatching(): ImageMatcherResult {\n return this.createMatcherResult('', true);\n }\n}\n\nexport function toMatchSnapshot(\n this: ExpectMatcherStateInternal,\n received: Buffer | string,\n nameOrOptions: NameOrSegments | { name?: NameOrSegments } & ImageComparatorOptions = {},\n optOptions: ImageComparatorOptions = {}\n): MatcherResult<NameOrSegments | { name?: NameOrSegments }, string> {\n const testInfo = currentTestInfo();\n if (!testInfo)\n throw new Error(`toMatchSnapshot() must be called during the test`);\n if (received instanceof Promise)\n throw new Error('An unresolved Promise was passed to toMatchSnapshot(), make sure to resolve it by adding await to it.');\n\n if (testInfo._projectInternal.ignoreSnapshots)\n return { pass: !this.isNot, message: () => '', name: 'toMatchSnapshot', expected: nameOrOptions };\n\n const configOptions = testInfo._projectInternal.expect?.toMatchSnapshot || {};\n const helper = new SnapshotHelper(\n testInfo, 'toMatchSnapshot', undefined, '.' + determineFileExtension(received),\n configOptions, nameOrOptions, optOptions);\n\n if (this.isNot) {\n if (!fs.existsSync(helper.expectedPath))\n return helper.handleMissingNegated();\n const isDifferent = !!helper.comparator(received, fs.readFileSync(helper.expectedPath), helper.options);\n return isDifferent ? helper.handleDifferentNegated() : helper.handleMatchingNegated();\n }\n\n if (!fs.existsSync(helper.expectedPath))\n return helper.handleMissing(received, this._stepInfo);\n\n const expected = fs.readFileSync(helper.expectedPath);\n\n if (helper.updateSnapshots === 'all') {\n if (!compareBuffersOrStrings(received, expected))\n return helper.handleMatching();\n writeFileSync(helper.expectedPath, received);\n /* eslint-disable no-console */\n console.log(helper.expectedPath + ' is not the same, writing actual.');\n return helper.createMatcherResult(helper.expectedPath + ' running with --update-snapshots, writing actual.', true);\n }\n\n if (helper.updateSnapshots === 'changed') {\n const result = helper.comparator(received, expected, helper.options);\n if (!result)\n return helper.handleMatching();\n writeFileSync(helper.expectedPath, received);\n /* eslint-disable no-console */\n console.log(helper.expectedPath + ' does not match, writing actual.');\n return helper.createMatcherResult(helper.expectedPath + ' running with --update-snapshots, writing actual.', true);\n }\n\n const result = helper.comparator(received, expected, helper.options);\n if (!result)\n return helper.handleMatching();\n\n const header = formatMatcherMessage(this, { matcherName: 'toMatchSnapshot', receiver: isString(received) ? 'string' : 'Buffer', expectation: 'expected' });\n return helper.handleDifferent(received, expected, undefined, result.diff, header, result.errorMessage, undefined, this._stepInfo);\n}\n\nexport function toHaveScreenshotStepTitle(\n nameOrOptions: NameOrSegments | { name?: NameOrSegments } & ToHaveScreenshotOptions = {},\n optOptions: ToHaveScreenshotOptions = {}\n): string {\n let name: NameOrSegments | undefined;\n if (typeof nameOrOptions === 'object' && !Array.isArray(nameOrOptions))\n name = nameOrOptions.name;\n else\n name = nameOrOptions;\n return Array.isArray(name) ? name.join(path.sep) : name || '';\n}\n\nexport async function toHaveScreenshot(\n this: ExpectMatcherStateInternal,\n pageOrLocator: Page | Locator,\n nameOrOptions: NameOrSegments | { name?: NameOrSegments } & ToHaveScreenshotOptions = {},\n optOptions: ToHaveScreenshotOptions = {}\n): Promise<MatcherResult<NameOrSegments | { name?: NameOrSegments }, string>> {\n const testInfo = currentTestInfo();\n if (!testInfo)\n throw new Error(`toHaveScreenshot() must be called during the test`);\n\n if (testInfo._projectInternal.ignoreSnapshots)\n return { pass: !this.isNot, message: () => '', name: 'toHaveScreenshot', expected: nameOrOptions };\n\n expectTypes(pageOrLocator, ['Page', 'Locator'], 'toHaveScreenshot');\n const [page, locator] = pageOrLocator.constructor.name === 'Page' ? [(pageOrLocator as PageEx), undefined] : [(pageOrLocator as Locator).page() as PageEx, pageOrLocator as Locator];\n const configOptions = testInfo._projectInternal.expect?.toHaveScreenshot || {};\n const helper = new SnapshotHelper(testInfo, 'toHaveScreenshot', locator, undefined, configOptions, nameOrOptions, optOptions);\n if (!helper.expectedPath.toLowerCase().endsWith('.png'))\n throw new Error(`Screenshot name \"${path.basename(helper.expectedPath)}\" must have '.png' extension`);\n expectTypes(pageOrLocator, ['Page', 'Locator'], 'toHaveScreenshot');\n const style = await loadScreenshotStyles(helper.options.stylePath);\n const timeout = helper.options.timeout ?? this.timeout;\n const expectScreenshotOptions: ExpectScreenshotOptions = {\n locator,\n animations: helper.options.animations ?? 'disabled',\n caret: helper.options.caret ?? 'hide',\n clip: helper.options.clip,\n fullPage: helper.options.fullPage,\n mask: helper.options.mask,\n maskColor: helper.options.maskColor,\n omitBackground: helper.options.omitBackground,\n scale: helper.options.scale ?? 'css',\n style,\n isNot: !!this.isNot,\n timeout,\n comparator: helper.options.comparator,\n maxDiffPixels: helper.options.maxDiffPixels,\n maxDiffPixelRatio: helper.options.maxDiffPixelRatio,\n threshold: helper.options.threshold,\n };\n\n const hasSnapshot = fs.existsSync(helper.expectedPath);\n if (this.isNot) {\n if (!hasSnapshot)\n return helper.handleMissingNegated();\n\n // Having `errorMessage` means we timed out while waiting\n // for screenshots not to match, so screenshots\n // are actually the same in the end.\n expectScreenshotOptions.expected = await fs.promises.readFile(helper.expectedPath);\n const isDifferent = !(await page._expectScreenshot(expectScreenshotOptions)).errorMessage;\n return isDifferent ? helper.handleDifferentNegated() : helper.handleMatchingNegated();\n }\n\n // Fast path: there's no screenshot and we don't intend to update it.\n if (helper.updateSnapshots === 'none' && !hasSnapshot)\n return helper.createMatcherResult(`A snapshot doesn't exist at ${helper.expectedPath}.`, false);\n\n if (!hasSnapshot) {\n // Regenerate a new screenshot by waiting until two screenshots are the same.\n const { actual, previous, diff, errorMessage, log, timedOut } = await page._expectScreenshot(expectScreenshotOptions);\n // We tried re-generating new snapshot but failed.\n // This can be due to e.g. spinning animation, so we want to show it as a diff.\n if (errorMessage) {\n const header = formatMatcherMessage(this, { matcherName: 'toHaveScreenshot', locator, expectation: 'expected', timeout, timedOut });\n return helper.handleDifferent(actual, undefined, previous, diff, header, errorMessage, log, this._stepInfo);\n }\n\n // We successfully generated new screenshot.\n return helper.handleMissing(actual!, this._stepInfo);\n }\n\n // General case:\n // - snapshot exists\n // - regular matcher (i.e. not a `.not`)\n const expected = await fs.promises.readFile(helper.expectedPath);\n expectScreenshotOptions.expected = helper.updateSnapshots === 'all' ? undefined : expected;\n\n const { actual, previous, diff, errorMessage, log, timedOut } = await page._expectScreenshot(expectScreenshotOptions);\n const writeFiles = (actualBuffer: Buffer) => {\n writeFileSync(helper.expectedPath, actualBuffer);\n writeFileSync(helper.actualPath, actualBuffer);\n /* eslint-disable no-console */\n console.log(helper.expectedPath + ' is re-generated, writing actual.');\n return helper.createMatcherResult(helper.expectedPath + ' running with --update-snapshots, writing actual.', true);\n };\n\n if (!errorMessage) {\n // Screenshot is matching, but is not necessarily the same as the expected.\n if (helper.updateSnapshots === 'all' && actual && compareBuffersOrStrings(actual, expected)) {\n console.log(helper.expectedPath + ' is re-generated, writing actual.');\n return writeFiles(actual);\n }\n return helper.handleMatching();\n }\n\n if (helper.updateSnapshots === 'changed' || helper.updateSnapshots === 'all') {\n if (actual)\n return writeFiles(actual);\n let header = formatMatcherMessage(this, { matcherName: 'toHaveScreenshot', locator, expectation: 'expected', timeout, timedOut });\n header += ' Failed to re-generate expected.\\n';\n return helper.handleDifferent(actual, expectScreenshotOptions.expected, previous, diff, header, errorMessage, log, this._stepInfo);\n }\n\n const header = formatMatcherMessage(this, { matcherName: 'toHaveScreenshot', locator, expectation: 'expected', timeout, timedOut });\n return helper.handleDifferent(actual, expectScreenshotOptions.expected, previous, diff, header, errorMessage, log, this._stepInfo);\n}\n\nfunction writeFileSync(aPath: string, content: Buffer | string) {\n fs.mkdirSync(path.dirname(aPath), { recursive: true });\n fs.writeFileSync(aPath, content);\n}\n\nfunction indent(lines: string, tab: string) {\n return lines.replace(/^(?=.+$)/gm, tab);\n}\n\nfunction determineFileExtension(file: string | Buffer): string {\n if (typeof file === 'string')\n return 'txt';\n if (compareMagicBytes(file, [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]))\n return 'png';\n if (compareMagicBytes(file, [0xff, 0xd8, 0xff]))\n return 'jpg';\n return 'dat';\n}\n\nfunction compareMagicBytes(file: Buffer, magicBytes: number[]): boolean {\n return Buffer.compare(Buffer.from(magicBytes), file.slice(0, magicBytes.length)) === 0;\n}\n\nasync function loadScreenshotStyles(stylePath?: string | string[]): Promise<string | undefined> {\n if (!stylePath)\n return;\n\n const stylePaths = Array.isArray(stylePath) ? stylePath : [stylePath];\n const styles = await Promise.all(stylePaths.map(async stylePath => {\n const text = await fs.promises.readFile(stylePath, 'utf8');\n return text.trim();\n }));\n return styles.join('\\n').trim() || undefined;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_utils", "path", "fs", "result", "actual", "previous", "diff", "errorMessage", "log", "timedOut", "header", "stylePath"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var toMatchText_exports = {};
|
|
20
|
+
__export(toMatchText_exports, {
|
|
21
|
+
toMatchText: () => toMatchText
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(toMatchText_exports);
|
|
24
|
+
var import_util = require("../util");
|
|
25
|
+
var import_expect = require("./expect");
|
|
26
|
+
var import_matcherHint = require("./matcherHint");
|
|
27
|
+
var import_expectBundle = require("../common/expectBundle");
|
|
28
|
+
async function toMatchText(matcherName, receiver, receiverType, query, expected, options = {}) {
|
|
29
|
+
(0, import_util.expectTypes)(receiver, [receiverType], matcherName);
|
|
30
|
+
const locator = receiverType === "Locator" ? receiver : void 0;
|
|
31
|
+
if (!(typeof expected === "string") && !(expected && typeof expected.test === "function")) {
|
|
32
|
+
const errorMessage2 = `Error: ${(0, import_expectBundle.EXPECTED_COLOR)("expected")} value must be a string or regular expression
|
|
33
|
+
${this.utils.printWithType("Expected", expected, this.utils.printExpected)}`;
|
|
34
|
+
throw new Error((0, import_matcherHint.formatMatcherMessage)(this, { locator, matcherName, expectation: "expected", errorMessage: errorMessage2 }));
|
|
35
|
+
}
|
|
36
|
+
const timeout = options.timeout ?? this.timeout;
|
|
37
|
+
const { matches: pass, received, log, timedOut, errorMessage } = await query(!!this.isNot, timeout);
|
|
38
|
+
if (pass === !this.isNot) {
|
|
39
|
+
return {
|
|
40
|
+
name: matcherName,
|
|
41
|
+
message: () => "",
|
|
42
|
+
pass,
|
|
43
|
+
expected
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const expectedSuffix = typeof expected === "string" ? options.matchSubstring ? " substring" : "" : " pattern";
|
|
47
|
+
const receivedSuffix = typeof expected === "string" ? options.matchSubstring ? " string" : "" : " string";
|
|
48
|
+
const receivedString = received || "";
|
|
49
|
+
let printedReceived;
|
|
50
|
+
let printedExpected;
|
|
51
|
+
let printedDiff;
|
|
52
|
+
if (pass) {
|
|
53
|
+
if (typeof expected === "string") {
|
|
54
|
+
printedExpected = `Expected${expectedSuffix}: not ${this.utils.printExpected(expected)}`;
|
|
55
|
+
if (!errorMessage) {
|
|
56
|
+
const formattedReceived = (0, import_expect.printReceivedStringContainExpectedSubstring)(receivedString, receivedString.indexOf(expected), expected.length);
|
|
57
|
+
printedReceived = `Received${receivedSuffix}: ${formattedReceived}`;
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
printedExpected = `Expected${expectedSuffix}: not ${this.utils.printExpected(expected)}`;
|
|
61
|
+
if (!errorMessage) {
|
|
62
|
+
const formattedReceived = (0, import_expect.printReceivedStringContainExpectedResult)(receivedString, typeof expected.exec === "function" ? expected.exec(receivedString) : null);
|
|
63
|
+
printedReceived = `Received${receivedSuffix}: ${formattedReceived}`;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
if (errorMessage)
|
|
68
|
+
printedExpected = `Expected${expectedSuffix}: ${this.utils.printExpected(expected)}`;
|
|
69
|
+
else
|
|
70
|
+
printedDiff = this.utils.printDiffOrStringify(expected, receivedString, `Expected${expectedSuffix}`, `Received${receivedSuffix}`, false);
|
|
71
|
+
}
|
|
72
|
+
const message = () => {
|
|
73
|
+
return (0, import_matcherHint.formatMatcherMessage)(this, {
|
|
74
|
+
matcherName,
|
|
75
|
+
expectation: "expected",
|
|
76
|
+
locator,
|
|
77
|
+
timeout,
|
|
78
|
+
timedOut,
|
|
79
|
+
printedExpected,
|
|
80
|
+
printedReceived,
|
|
81
|
+
printedDiff,
|
|
82
|
+
log,
|
|
83
|
+
errorMessage
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
return {
|
|
87
|
+
name: matcherName,
|
|
88
|
+
expected,
|
|
89
|
+
message,
|
|
90
|
+
pass,
|
|
91
|
+
actual: received,
|
|
92
|
+
log,
|
|
93
|
+
timeout: timedOut ? timeout : void 0
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
97
|
+
0 && (module.exports = {
|
|
98
|
+
toMatchText
|
|
99
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/matchers/toMatchText.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright Microsoft Corporation. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n\nimport { expectTypes } from '../util';\nimport {\n printReceivedStringContainExpectedResult,\n printReceivedStringContainExpectedSubstring\n} from './expect';\nimport { formatMatcherMessage } from './matcherHint';\nimport { EXPECTED_COLOR } from '../common/expectBundle';\n\nimport type { MatcherResult } from './matcherHint';\nimport type { ExpectMatcherState } from '../../types/test';\nimport type { Page, Locator } from 'playwright-core';\n\nexport async function toMatchText(\n this: ExpectMatcherState,\n matcherName: string,\n receiver: Locator | Page,\n receiverType: 'Locator' | 'Page',\n query: (isNot: boolean, timeout: number) => Promise<{ matches: boolean, received?: string, log?: string[], timedOut?: boolean, errorMessage?: string }>,\n expected: string | RegExp,\n options: { timeout?: number, matchSubstring?: boolean } = {},\n): Promise<MatcherResult<string | RegExp, string>> {\n expectTypes(receiver, [receiverType], matcherName);\n const locator = receiverType === 'Locator' ? receiver as Locator : undefined;\n\n if (\n !(typeof expected === 'string') &&\n !(expected && typeof expected.test === 'function')\n ) {\n const errorMessage = `Error: ${EXPECTED_COLOR('expected')} value must be a string or regular expression\\n${this.utils.printWithType('Expected', expected, this.utils.printExpected)}`;\n throw new Error(formatMatcherMessage(this, { locator, matcherName, expectation: 'expected', errorMessage }));\n }\n\n const timeout = options.timeout ?? this.timeout;\n\n const { matches: pass, received, log, timedOut, errorMessage } = await query(!!this.isNot, timeout);\n\n if (pass === !this.isNot) {\n return {\n name: matcherName,\n message: () => '',\n pass,\n expected\n };\n }\n\n const expectedSuffix = typeof expected === 'string' ? (options.matchSubstring ? ' substring' : '') : ' pattern';\n const receivedSuffix = typeof expected === 'string' ? (options.matchSubstring ? ' string' : '') : ' string';\n const receivedString = received || '';\n let printedReceived: string | undefined;\n let printedExpected: string | undefined;\n let printedDiff: string | undefined;\n if (pass) {\n if (typeof expected === 'string') {\n printedExpected = `Expected${expectedSuffix}: not ${this.utils.printExpected(expected)}`;\n if (!errorMessage) {\n const formattedReceived = printReceivedStringContainExpectedSubstring(receivedString, receivedString.indexOf(expected), expected.length);\n printedReceived = `Received${receivedSuffix}: ${formattedReceived}`;\n }\n } else {\n printedExpected = `Expected${expectedSuffix}: not ${this.utils.printExpected(expected)}`;\n if (!errorMessage) {\n const formattedReceived = printReceivedStringContainExpectedResult(receivedString, typeof expected.exec === 'function' ? expected.exec(receivedString) : null);\n printedReceived = `Received${receivedSuffix}: ${formattedReceived}`;\n }\n }\n } else {\n if (errorMessage)\n printedExpected = `Expected${expectedSuffix}: ${this.utils.printExpected(expected)}`;\n else\n printedDiff = this.utils.printDiffOrStringify(expected, receivedString, `Expected${expectedSuffix}`, `Received${receivedSuffix}`, false);\n }\n\n const message = () => {\n return formatMatcherMessage(this, {\n matcherName,\n expectation: 'expected',\n locator,\n timeout,\n timedOut,\n printedExpected,\n printedReceived,\n printedDiff,\n log,\n errorMessage,\n });\n };\n\n return {\n name: matcherName,\n expected,\n message,\n pass,\n actual: received,\n log,\n timeout: timedOut ? timeout : undefined,\n };\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBA,kBAA4B;AAC5B,oBAGO;AACP,yBAAqC;AACrC,0BAA+B;AAM/B,eAAsB,YAEpB,aACA,UACA,cACA,OACA,UACA,UAA0D,CAAC,GACV;AACjD,+BAAY,UAAU,CAAC,YAAY,GAAG,WAAW;AACjD,QAAM,UAAU,iBAAiB,YAAY,WAAsB;AAEnE,MACE,EAAE,OAAO,aAAa,aACtB,EAAE,YAAY,OAAO,SAAS,SAAS,aACvC;AACA,UAAMA,gBAAe,cAAU,oCAAe,UAAU,CAAC;AAAA,EAAkD,KAAK,MAAM,cAAc,YAAY,UAAU,KAAK,MAAM,aAAa,CAAC;AACnL,UAAM,IAAI,UAAM,yCAAqB,MAAM,EAAE,SAAS,aAAa,aAAa,YAAY,cAAAA,cAAa,CAAC,CAAC;AAAA,EAC7G;AAEA,QAAM,UAAU,QAAQ,WAAW,KAAK;AAExC,QAAM,EAAE,SAAS,MAAM,UAAU,KAAK,UAAU,aAAa,IAAI,MAAM,MAAM,CAAC,CAAC,KAAK,OAAO,OAAO;AAElG,MAAI,SAAS,CAAC,KAAK,OAAO;AACxB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS,MAAM;AAAA,MACf;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,iBAAiB,OAAO,aAAa,WAAY,QAAQ,iBAAiB,eAAe,KAAM;AACrG,QAAM,iBAAiB,OAAO,aAAa,WAAY,QAAQ,iBAAiB,YAAY,KAAM;AAClG,QAAM,iBAAiB,YAAY;AACnC,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI,MAAM;AACR,QAAI,OAAO,aAAa,UAAU;AAChC,wBAAkB,WAAW,cAAc,SAAS,KAAK,MAAM,cAAc,QAAQ,CAAC;AACtF,UAAI,CAAC,cAAc;AACjB,cAAM,wBAAoB,2DAA4C,gBAAgB,eAAe,QAAQ,QAAQ,GAAG,SAAS,MAAM;AACvI,0BAAkB,WAAW,cAAc,KAAK,iBAAiB;AAAA,MACnE;AAAA,IACF,OAAO;AACL,wBAAkB,WAAW,cAAc,SAAS,KAAK,MAAM,cAAc,QAAQ,CAAC;AACtF,UAAI,CAAC,cAAc;AACjB,cAAM,wBAAoB,wDAAyC,gBAAgB,OAAO,SAAS,SAAS,aAAa,SAAS,KAAK,cAAc,IAAI,IAAI;AAC7J,0BAAkB,WAAW,cAAc,KAAK,iBAAiB;AAAA,MACnE;AAAA,IACF;AAAA,EACF,OAAO;AACL,QAAI;AACF,wBAAkB,WAAW,cAAc,KAAK,KAAK,MAAM,cAAc,QAAQ,CAAC;AAAA;AAElF,oBAAc,KAAK,MAAM,qBAAqB,UAAU,gBAAgB,WAAW,cAAc,IAAI,WAAW,cAAc,IAAI,KAAK;AAAA,EAC3I;AAEA,QAAM,UAAU,MAAM;AACpB,eAAO,yCAAqB,MAAM;AAAA,MAChC;AAAA,MACA,aAAa;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA,SAAS,WAAW,UAAU;AAAA,EAChC;AACF;",
|
|
6
|
+
"names": ["errorMessage"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __copyProps = (to, from, except, desc) => {
|
|
7
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
+
for (let key of __getOwnPropNames(from))
|
|
9
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
+
}
|
|
12
|
+
return to;
|
|
13
|
+
};
|
|
14
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
+
var actions_d_exports = {};
|
|
16
|
+
module.exports = __toCommonJS(actions_d_exports);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/mcp/browser/actions.d.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ntype Point = { x: number, y: number };\n\nexport type ActionName =\n 'check' |\n 'click' |\n 'closePage' |\n 'fill' |\n 'navigate' |\n 'openPage' |\n 'press' |\n 'select' |\n 'uncheck' |\n 'setInputFiles' |\n 'assertText' |\n 'assertValue' |\n 'assertChecked' |\n 'assertVisible' |\n 'assertSnapshot';\n\nexport type ActionBase = {\n name: ActionName,\n signals: Signal[],\n ariaSnapshot?: string,\n};\n\nexport type ActionWithSelector = ActionBase & {\n selector: string,\n ref?: string,\n};\n\nexport type ClickAction = ActionWithSelector & {\n name: 'click',\n button: 'left' | 'middle' | 'right',\n modifiers: number,\n clickCount: number,\n position?: Point,\n};\n\nexport type CheckAction = ActionWithSelector & {\n name: 'check',\n};\n\nexport type UncheckAction = ActionWithSelector & {\n name: 'uncheck',\n};\n\nexport type FillAction = ActionWithSelector & {\n name: 'fill',\n text: string,\n};\n\nexport type NavigateAction = ActionBase & {\n name: 'navigate',\n url: string,\n};\n\nexport type OpenPageAction = ActionBase & {\n name: 'openPage',\n url: string,\n};\n\nexport type ClosesPageAction = ActionBase & {\n name: 'closePage',\n};\n\nexport type PressAction = ActionWithSelector & {\n name: 'press',\n key: string,\n modifiers: number,\n};\n\nexport type SelectAction = ActionWithSelector & {\n name: 'select',\n options: string[],\n};\n\nexport type SetInputFilesAction = ActionWithSelector & {\n name: 'setInputFiles',\n files: string[],\n};\n\nexport type AssertTextAction = ActionWithSelector & {\n name: 'assertText',\n text: string,\n substring: boolean,\n};\n\nexport type AssertValueAction = ActionWithSelector & {\n name: 'assertValue',\n value: string,\n};\n\nexport type AssertCheckedAction = ActionWithSelector & {\n name: 'assertChecked',\n checked: boolean,\n};\n\nexport type AssertVisibleAction = ActionWithSelector & {\n name: 'assertVisible',\n};\n\nexport type AssertSnapshotAction = ActionWithSelector & {\n name: 'assertSnapshot',\n ariaSnapshot: string,\n};\n\nexport type Action = ClickAction | CheckAction | ClosesPageAction | OpenPageAction | UncheckAction | FillAction | NavigateAction | PressAction | SelectAction | SetInputFilesAction | AssertTextAction | AssertValueAction | AssertCheckedAction | AssertVisibleAction | AssertSnapshotAction;\nexport type AssertAction = AssertCheckedAction | AssertValueAction | AssertTextAction | AssertVisibleAction | AssertSnapshotAction;\nexport type PerformOnRecordAction = ClickAction | CheckAction | UncheckAction | PressAction | SelectAction;\n\n// Signals.\n\nexport type BaseSignal = {\n};\n\nexport type NavigationSignal = BaseSignal & {\n name: 'navigation',\n url: string,\n};\n\nexport type PopupSignal = BaseSignal & {\n name: 'popup',\n popupAlias: string,\n};\n\nexport type DownloadSignal = BaseSignal & {\n name: 'download',\n downloadAlias: string,\n};\n\nexport type DialogSignal = BaseSignal & {\n name: 'dialog',\n dialogAlias: string,\n};\n\nexport type Signal = NavigationSignal | PopupSignal | DownloadSignal | DialogSignal;\n\nexport type FrameDescription = {\n pageGuid: string;\n pageAlias: string;\n framePath: string[];\n};\n\nexport type ActionInContext = {\n frame: FrameDescription;\n description?: string;\n action: Action;\n startTime: number;\n endTime?: number;\n};\n\nexport type SignalInContext = {\n frame: FrameDescription;\n signal: Signal;\n timestamp: number;\n};\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;AAAA;AAAA;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var browserContextFactory_exports = {};
|
|
30
|
+
__export(browserContextFactory_exports, {
|
|
31
|
+
SharedContextFactory: () => SharedContextFactory,
|
|
32
|
+
contextFactory: () => contextFactory
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(browserContextFactory_exports);
|
|
35
|
+
var import_crypto = __toESM(require("crypto"));
|
|
36
|
+
var import_fs = __toESM(require("fs"));
|
|
37
|
+
var import_net = __toESM(require("net"));
|
|
38
|
+
var import_path = __toESM(require("path"));
|
|
39
|
+
var playwright = __toESM(require("playwright-core"));
|
|
40
|
+
var import_registry = require("playwright-core/lib/server/registry/index");
|
|
41
|
+
var import_server = require("playwright-core/lib/server");
|
|
42
|
+
var import_log = require("../log");
|
|
43
|
+
var import_config = require("./config");
|
|
44
|
+
var import_server2 = require("../sdk/server");
|
|
45
|
+
function contextFactory(config) {
|
|
46
|
+
if (config.sharedBrowserContext)
|
|
47
|
+
return SharedContextFactory.create(config);
|
|
48
|
+
if (config.browser.remoteEndpoint)
|
|
49
|
+
return new RemoteContextFactory(config);
|
|
50
|
+
if (config.browser.cdpEndpoint)
|
|
51
|
+
return new CdpContextFactory(config);
|
|
52
|
+
if (config.browser.isolated)
|
|
53
|
+
return new IsolatedContextFactory(config);
|
|
54
|
+
return new PersistentContextFactory(config);
|
|
55
|
+
}
|
|
56
|
+
class BaseContextFactory {
|
|
57
|
+
static {
|
|
58
|
+
this._cache = /* @__PURE__ */ new Map();
|
|
59
|
+
}
|
|
60
|
+
constructor(name, config) {
|
|
61
|
+
this._logName = name;
|
|
62
|
+
this.config = config;
|
|
63
|
+
}
|
|
64
|
+
_obtainBrowser(clientInfo) {
|
|
65
|
+
const key = this._calcFingerprint();
|
|
66
|
+
if (BaseContextFactory._cache.has(key)) {
|
|
67
|
+
return BaseContextFactory._cache.get(key);
|
|
68
|
+
}
|
|
69
|
+
(0, import_log.testDebug)(`obtain browser (${this._logName})`);
|
|
70
|
+
const browserPromise = this._doObtainBrowser(clientInfo);
|
|
71
|
+
void browserPromise.then((browser) => {
|
|
72
|
+
browser.on("disconnected", () => {
|
|
73
|
+
BaseContextFactory._cache.delete(key);
|
|
74
|
+
});
|
|
75
|
+
}).catch(() => {
|
|
76
|
+
BaseContextFactory._cache.delete(key);
|
|
77
|
+
});
|
|
78
|
+
BaseContextFactory._cache.set(key, browserPromise);
|
|
79
|
+
return browserPromise;
|
|
80
|
+
}
|
|
81
|
+
_calcFingerprint() {
|
|
82
|
+
const relevantConfig = this._extractRelevantConfig();
|
|
83
|
+
const fingerprintData = {
|
|
84
|
+
name: this._logName,
|
|
85
|
+
config: relevantConfig
|
|
86
|
+
};
|
|
87
|
+
const stableJson = stableStringify(fingerprintData);
|
|
88
|
+
return import_crypto.default.createHash("sha256").update(stableJson).digest("hex");
|
|
89
|
+
}
|
|
90
|
+
_extractRelevantConfig() {
|
|
91
|
+
throw new Error("Not implemented");
|
|
92
|
+
}
|
|
93
|
+
async _doObtainBrowser(clientInfo) {
|
|
94
|
+
throw new Error("Not implemented");
|
|
95
|
+
}
|
|
96
|
+
async createContext(clientInfo) {
|
|
97
|
+
(0, import_log.testDebug)(`create browser context (${this._logName}), config: ${JSON.stringify(this.config)}`);
|
|
98
|
+
const browser = await this._obtainBrowser(clientInfo);
|
|
99
|
+
const browserContext = await this._doCreateContext(browser);
|
|
100
|
+
await addInitScript(browserContext, this.config.browser.initScript);
|
|
101
|
+
return {
|
|
102
|
+
browserContext,
|
|
103
|
+
close: (afterClose) => this._closeBrowserContext(browserContext, browser, afterClose)
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
async _doCreateContext(browser) {
|
|
107
|
+
throw new Error("Not implemented");
|
|
108
|
+
}
|
|
109
|
+
async _closeBrowserContext(browserContext, browser, afterClose) {
|
|
110
|
+
(0, import_log.testDebug)(`close browser context (${this._logName})`);
|
|
111
|
+
if (browser.contexts().length === 1) {
|
|
112
|
+
const key = this._calcFingerprint();
|
|
113
|
+
BaseContextFactory._cache.delete(key);
|
|
114
|
+
}
|
|
115
|
+
await browserContext.close().catch(import_log.logUnhandledError);
|
|
116
|
+
await afterClose();
|
|
117
|
+
if (browser.contexts().length === 0) {
|
|
118
|
+
(0, import_log.testDebug)(`close browser (${this._logName})`);
|
|
119
|
+
await browser.close().catch(import_log.logUnhandledError);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
class IsolatedContextFactory extends BaseContextFactory {
|
|
124
|
+
constructor(config) {
|
|
125
|
+
super("isolated", config);
|
|
126
|
+
}
|
|
127
|
+
async _doObtainBrowser(clientInfo) {
|
|
128
|
+
const launchOptions = await injectCdpPort(this.config.browser);
|
|
129
|
+
const browserType = playwright[this.config.browser.browserName];
|
|
130
|
+
const tracesDir = await computeTracesDir(this.config, clientInfo);
|
|
131
|
+
if (tracesDir && this.config.saveTrace)
|
|
132
|
+
await startTraceServer(this.config, tracesDir);
|
|
133
|
+
return browserType.launch({
|
|
134
|
+
tracesDir,
|
|
135
|
+
...launchOptions,
|
|
136
|
+
handleSIGINT: false,
|
|
137
|
+
handleSIGTERM: false
|
|
138
|
+
}).catch((error) => {
|
|
139
|
+
if (error.message.includes("Executable doesn't exist"))
|
|
140
|
+
throw new Error(`Browser specified in your config is not installed. Either install it (likely) or change the config.`);
|
|
141
|
+
throw error;
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
_extractRelevantConfig() {
|
|
145
|
+
return {
|
|
146
|
+
browserName: this.config.browser.browserName,
|
|
147
|
+
launchOptions: this.config.browser.launchOptions,
|
|
148
|
+
saveTrace: this.config.saveTrace
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
async _doCreateContext(browser) {
|
|
152
|
+
return browser.newContext(this.config.browser.contextOptions);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
class CdpContextFactory extends BaseContextFactory {
|
|
156
|
+
constructor(config) {
|
|
157
|
+
super("cdp", config);
|
|
158
|
+
}
|
|
159
|
+
async _doObtainBrowser() {
|
|
160
|
+
return playwright.chromium.connectOverCDP(this.config.browser.cdpEndpoint, { headers: this.config.browser.cdpHeaders });
|
|
161
|
+
}
|
|
162
|
+
_extractRelevantConfig() {
|
|
163
|
+
return {
|
|
164
|
+
cdpEndpoint: this.config.browser.cdpEndpoint,
|
|
165
|
+
cdpHeaders: this.config.browser.cdpHeaders
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
async _doCreateContext(browser) {
|
|
169
|
+
return this.config.browser.isolated ? await browser.newContext() : browser.contexts()[0];
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
class RemoteContextFactory extends BaseContextFactory {
|
|
173
|
+
constructor(config) {
|
|
174
|
+
super("remote", config);
|
|
175
|
+
}
|
|
176
|
+
async _doObtainBrowser() {
|
|
177
|
+
const url = new URL(this.config.browser.remoteEndpoint);
|
|
178
|
+
url.searchParams.set("browser", this.config.browser.browserName);
|
|
179
|
+
if (this.config.browser.launchOptions)
|
|
180
|
+
url.searchParams.set("launch-options", JSON.stringify(this.config.browser.launchOptions));
|
|
181
|
+
return playwright[this.config.browser.browserName].connect(String(url));
|
|
182
|
+
}
|
|
183
|
+
_extractRelevantConfig() {
|
|
184
|
+
return {
|
|
185
|
+
remoteEndpoint: this.config.browser.remoteEndpoint,
|
|
186
|
+
browserName: this.config.browser.browserName,
|
|
187
|
+
launchOptions: this.config.browser.launchOptions
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
async _doCreateContext(browser) {
|
|
191
|
+
return browser.newContext();
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
class PersistentContextFactory {
|
|
195
|
+
constructor(config) {
|
|
196
|
+
this.name = "persistent";
|
|
197
|
+
this.description = "Create a new persistent browser context";
|
|
198
|
+
this._userDataDirs = /* @__PURE__ */ new Set();
|
|
199
|
+
this.config = config;
|
|
200
|
+
}
|
|
201
|
+
async createContext(clientInfo) {
|
|
202
|
+
const launchOptionsWithCdp = await injectCdpPort(this.config.browser);
|
|
203
|
+
(0, import_log.testDebug)("create browser context (persistent)");
|
|
204
|
+
const userDataDir = this.config.browser.userDataDir ?? await this._createUserDataDir(clientInfo);
|
|
205
|
+
const tracesDir = await computeTracesDir(this.config, clientInfo);
|
|
206
|
+
if (tracesDir && this.config.saveTrace)
|
|
207
|
+
await startTraceServer(this.config, tracesDir);
|
|
208
|
+
this._userDataDirs.add(userDataDir);
|
|
209
|
+
(0, import_log.testDebug)("lock user data dir", userDataDir);
|
|
210
|
+
const browserType = playwright[this.config.browser.browserName];
|
|
211
|
+
for (let i = 0; i < 5; i++) {
|
|
212
|
+
const launchPersistentOptions = {
|
|
213
|
+
tracesDir,
|
|
214
|
+
...launchOptionsWithCdp,
|
|
215
|
+
...this.config.browser.contextOptions,
|
|
216
|
+
handleSIGINT: false,
|
|
217
|
+
handleSIGTERM: false,
|
|
218
|
+
ignoreDefaultArgs: [
|
|
219
|
+
"--disable-extensions"
|
|
220
|
+
],
|
|
221
|
+
assistantMode: true
|
|
222
|
+
};
|
|
223
|
+
try {
|
|
224
|
+
const browserContext = await browserType.launchPersistentContext(userDataDir, launchPersistentOptions);
|
|
225
|
+
await addInitScript(browserContext, this.config.browser.initScript);
|
|
226
|
+
const close = (afterClose) => this._closeBrowserContext(browserContext, userDataDir, afterClose);
|
|
227
|
+
return { browserContext, close };
|
|
228
|
+
} catch (error) {
|
|
229
|
+
if (error.message.includes("Executable doesn't exist"))
|
|
230
|
+
throw new Error(`Browser specified in your config is not installed. Either install it (likely) or change the config.`);
|
|
231
|
+
if (error.message.includes("ProcessSingleton") || error.message.includes("Invalid URL")) {
|
|
232
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
throw error;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
throw new Error(`Browser is already in use for ${userDataDir}, use --isolated to run multiple instances of the same browser`);
|
|
239
|
+
}
|
|
240
|
+
async _closeBrowserContext(browserContext, userDataDir, afterClose) {
|
|
241
|
+
(0, import_log.testDebug)("close browser context (persistent)");
|
|
242
|
+
(0, import_log.testDebug)("release user data dir", userDataDir);
|
|
243
|
+
await browserContext.close().catch(() => {
|
|
244
|
+
});
|
|
245
|
+
await afterClose();
|
|
246
|
+
this._userDataDirs.delete(userDataDir);
|
|
247
|
+
(0, import_log.testDebug)("close browser context complete (persistent)");
|
|
248
|
+
}
|
|
249
|
+
async _createUserDataDir(clientInfo) {
|
|
250
|
+
const dir = process.env.PWMCP_PROFILES_DIR_FOR_TEST ?? import_registry.registryDirectory;
|
|
251
|
+
const browserToken = this.config.browser.launchOptions?.channel ?? this.config.browser?.browserName;
|
|
252
|
+
const rootPath = (0, import_server2.firstRootPath)(clientInfo);
|
|
253
|
+
const rootPathToken = rootPath ? `-${createHash(rootPath)}` : "";
|
|
254
|
+
const result = import_path.default.join(dir, `mcp-${browserToken}${rootPathToken}`);
|
|
255
|
+
await import_fs.default.promises.mkdir(result, { recursive: true });
|
|
256
|
+
return result;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
async function injectCdpPort(browserConfig) {
|
|
260
|
+
if (browserConfig.browserName === "chromium") {
|
|
261
|
+
const cdpPort = await findFreePort();
|
|
262
|
+
return { ...browserConfig.launchOptions, cdpPort };
|
|
263
|
+
}
|
|
264
|
+
return browserConfig.launchOptions;
|
|
265
|
+
}
|
|
266
|
+
async function findFreePort() {
|
|
267
|
+
return new Promise((resolve, reject) => {
|
|
268
|
+
const server = import_net.default.createServer();
|
|
269
|
+
server.listen(0, () => {
|
|
270
|
+
const { port } = server.address();
|
|
271
|
+
server.close(() => resolve(port));
|
|
272
|
+
});
|
|
273
|
+
server.on("error", reject);
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
async function startTraceServer(config, tracesDir) {
|
|
277
|
+
if (!config.saveTrace)
|
|
278
|
+
return;
|
|
279
|
+
const server = await (0, import_server.startTraceViewerServer)();
|
|
280
|
+
const urlPrefix = server.urlPrefix("human-readable");
|
|
281
|
+
const url = urlPrefix + "/trace/index.html?trace=" + tracesDir + "/trace.json";
|
|
282
|
+
console.error("\nTrace viewer listening on " + url);
|
|
283
|
+
}
|
|
284
|
+
function createHash(data) {
|
|
285
|
+
return import_crypto.default.createHash("sha256").update(data).digest("hex").slice(0, 7);
|
|
286
|
+
}
|
|
287
|
+
async function addInitScript(browserContext, initScript) {
|
|
288
|
+
for (const scriptPath of initScript ?? [])
|
|
289
|
+
await browserContext.addInitScript({ path: import_path.default.resolve(scriptPath) });
|
|
290
|
+
}
|
|
291
|
+
class SharedContextFactory {
|
|
292
|
+
static create(config) {
|
|
293
|
+
if (SharedContextFactory._instance)
|
|
294
|
+
return SharedContextFactory._instance;
|
|
295
|
+
;
|
|
296
|
+
const baseConfig = { ...config, sharedBrowserContext: false };
|
|
297
|
+
const baseFactory = contextFactory(baseConfig);
|
|
298
|
+
SharedContextFactory._instance = new SharedContextFactory(baseFactory);
|
|
299
|
+
return SharedContextFactory._instance;
|
|
300
|
+
}
|
|
301
|
+
constructor(baseFactory) {
|
|
302
|
+
this._baseFactory = baseFactory;
|
|
303
|
+
}
|
|
304
|
+
async createContext(clientInfo, abortSignal, toolName) {
|
|
305
|
+
if (!this._contextPromise) {
|
|
306
|
+
(0, import_log.testDebug)("create shared browser context");
|
|
307
|
+
this._contextPromise = this._baseFactory.createContext(clientInfo, abortSignal, toolName);
|
|
308
|
+
}
|
|
309
|
+
const { browserContext } = await this._contextPromise;
|
|
310
|
+
(0, import_log.testDebug)(`shared context client connected`);
|
|
311
|
+
return {
|
|
312
|
+
browserContext,
|
|
313
|
+
close: async () => {
|
|
314
|
+
(0, import_log.testDebug)(`shared context client disconnected`);
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
static async dispose() {
|
|
319
|
+
await SharedContextFactory._instance?._dispose();
|
|
320
|
+
SharedContextFactory._instance = void 0;
|
|
321
|
+
}
|
|
322
|
+
async _dispose() {
|
|
323
|
+
const contextPromise = this._contextPromise;
|
|
324
|
+
this._contextPromise = void 0;
|
|
325
|
+
if (!contextPromise)
|
|
326
|
+
return;
|
|
327
|
+
const { close } = await contextPromise;
|
|
328
|
+
await close(async () => {
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
async function computeTracesDir(config, clientInfo) {
|
|
333
|
+
if (!config.saveTrace && !config.capabilities?.includes("tracing"))
|
|
334
|
+
return;
|
|
335
|
+
return await (0, import_config.outputFile)(config, clientInfo, `traces`, { origin: "code", reason: "Collecting trace" });
|
|
336
|
+
}
|
|
337
|
+
function stableStringify(obj) {
|
|
338
|
+
if (obj === null || obj === void 0) {
|
|
339
|
+
return String(obj);
|
|
340
|
+
}
|
|
341
|
+
if (typeof obj !== "object") {
|
|
342
|
+
return JSON.stringify(obj);
|
|
343
|
+
}
|
|
344
|
+
if (Array.isArray(obj)) {
|
|
345
|
+
return "[" + obj.map((item) => stableStringify(item)).join(",") + "]";
|
|
346
|
+
}
|
|
347
|
+
const sortedKeys = Object.keys(obj).sort();
|
|
348
|
+
const pairs = sortedKeys.map((key) => {
|
|
349
|
+
return JSON.stringify(key) + ":" + stableStringify(obj[key]);
|
|
350
|
+
});
|
|
351
|
+
return "{" + pairs.join(",") + "}";
|
|
352
|
+
}
|
|
353
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
354
|
+
0 && (module.exports = {
|
|
355
|
+
SharedContextFactory,
|
|
356
|
+
contextFactory
|
|
357
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/mcp/browser/browserContextFactory.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright (c) Microsoft Corporation.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport crypto from 'crypto';\nimport fs from 'fs';\nimport net from 'net';\nimport path from 'path';\n\nimport * as playwright from 'playwright-core';\nimport { registryDirectory } from 'playwright-core/lib/server/registry/index';\nimport { startTraceViewerServer } from 'playwright-core/lib/server';\nimport { logUnhandledError, testDebug } from '../log';\nimport { outputFile } from './config';\nimport { firstRootPath } from '../sdk/server';\n\nimport type { FullConfig } from './config';\nimport type { LaunchOptions, BrowserContextOptions } from '../../../../playwright-core/src/client/types';\nimport type { ClientInfo } from '../sdk/server';\n\nexport function contextFactory(config: FullConfig): BrowserContextFactory {\n if (config.sharedBrowserContext)\n return SharedContextFactory.create(config);\n if (config.browser.remoteEndpoint)\n return new RemoteContextFactory(config);\n if (config.browser.cdpEndpoint)\n return new CdpContextFactory(config);\n if (config.browser.isolated)\n return new IsolatedContextFactory(config);\n return new PersistentContextFactory(config);\n}\n\nexport type BrowserContextFactoryResult = {\n browserContext: playwright.BrowserContext;\n close: (afterClose: () => Promise<void>) => Promise<void>;\n};\n\nexport interface BrowserContextFactory {\n createContext(clientInfo: ClientInfo, abortSignal: AbortSignal, toolName: string | undefined): Promise<BrowserContextFactoryResult>;\n}\n\nclass BaseContextFactory implements BrowserContextFactory {\n readonly config: FullConfig;\n private _logName: string;\n private static _cache = new Map<string, Promise<playwright.Browser>>();\n\n constructor(name: string, config: FullConfig) {\n this._logName = name;\n this.config = config;\n }\n\n protected _obtainBrowser(clientInfo: ClientInfo): Promise<playwright.Browser> {\n const key = this._calcFingerprint();\n if (BaseContextFactory._cache.has(key)) {\n return BaseContextFactory._cache.get(key)!;\n }\n testDebug(`obtain browser (${this._logName})`);\n const browserPromise = this._doObtainBrowser(clientInfo);\n void browserPromise.then(browser => {\n browser.on('disconnected', () => {\n BaseContextFactory._cache.delete(key);\n });\n }).catch(() => {\n BaseContextFactory._cache.delete(key);\n });\n BaseContextFactory._cache.set(key, browserPromise);\n return browserPromise;\n }\n\n protected _calcFingerprint(): string {\n const relevantConfig = this._extractRelevantConfig();\n const fingerprintData = {\n name: this._logName,\n config: relevantConfig\n };\n const stableJson = stableStringify(fingerprintData);\n return crypto.createHash('sha256').update(stableJson).digest('hex');\n }\n\n protected _extractRelevantConfig(): any {\n throw new Error('Not implemented');\n }\n\n protected async _doObtainBrowser(clientInfo: ClientInfo): Promise<playwright.Browser> {\n throw new Error('Not implemented');\n }\n\n async createContext(clientInfo: ClientInfo): Promise<BrowserContextFactoryResult> {\n testDebug(`create browser context (${this._logName}), config: ${JSON.stringify(this.config)}`);\n const browser = await this._obtainBrowser(clientInfo);\n const browserContext = await this._doCreateContext(browser);\n await addInitScript(browserContext, this.config.browser.initScript);\n return {\n browserContext,\n close: (afterClose: () => Promise<void>) => this._closeBrowserContext(browserContext, browser, afterClose)\n };\n }\n\n protected async _doCreateContext(browser: playwright.Browser): Promise<playwright.BrowserContext> {\n throw new Error('Not implemented');\n }\n\n private async _closeBrowserContext(browserContext: playwright.BrowserContext, browser: playwright.Browser, afterClose: () => Promise<void>) {\n testDebug(`close browser context (${this._logName})`);\n if (browser.contexts().length === 1){\n const key = this._calcFingerprint();\n BaseContextFactory._cache.delete(key);\n }\n await browserContext.close().catch(logUnhandledError);\n await afterClose();\n if (browser.contexts().length === 0) {\n testDebug(`close browser (${this._logName})`);\n await browser.close().catch(logUnhandledError);\n }\n }\n}\n\nclass IsolatedContextFactory extends BaseContextFactory {\n constructor(config: FullConfig) {\n super('isolated', config);\n }\n\n protected override async _doObtainBrowser(clientInfo: ClientInfo): Promise<playwright.Browser> {\n const launchOptions = await injectCdpPort(this.config.browser);\n const browserType = playwright[this.config.browser.browserName];\n const tracesDir = await computeTracesDir(this.config, clientInfo);\n if (tracesDir && this.config.saveTrace)\n await startTraceServer(this.config, tracesDir);\n return browserType.launch({\n tracesDir,\n ...launchOptions,\n handleSIGINT: false,\n handleSIGTERM: false,\n }).catch(error => {\n if (error.message.includes('Executable doesn\\'t exist'))\n throw new Error(`Browser specified in your config is not installed. Either install it (likely) or change the config.`);\n throw error;\n });\n }\n\n protected override _extractRelevantConfig(): any {\n return {\n browserName: this.config.browser.browserName,\n launchOptions: this.config.browser.launchOptions,\n saveTrace: this.config.saveTrace,\n };\n }\n\n protected override async _doCreateContext(browser: playwright.Browser): Promise<playwright.BrowserContext> {\n\n return browser.newContext(this.config.browser.contextOptions);\n }\n}\n\nclass CdpContextFactory extends BaseContextFactory {\n constructor(config: FullConfig) {\n super('cdp', config);\n }\n\n protected override async _doObtainBrowser(): Promise<playwright.Browser> {\n return playwright.chromium.connectOverCDP(this.config.browser.cdpEndpoint!, { headers: this.config.browser.cdpHeaders });\n }\n\n protected override _extractRelevantConfig(): any {\n return {\n cdpEndpoint: this.config.browser.cdpEndpoint,\n cdpHeaders: this.config.browser.cdpHeaders,\n };\n }\n\n protected override async _doCreateContext(browser: playwright.Browser): Promise<playwright.BrowserContext> {\n return this.config.browser.isolated ? await browser.newContext() : browser.contexts()[0];\n }\n}\n\nclass RemoteContextFactory extends BaseContextFactory {\n constructor(config: FullConfig) {\n super('remote', config);\n }\n\n protected override async _doObtainBrowser(): Promise<playwright.Browser> {\n const url = new URL(this.config.browser.remoteEndpoint!);\n url.searchParams.set('browser', this.config.browser.browserName);\n if (this.config.browser.launchOptions)\n url.searchParams.set('launch-options', JSON.stringify(this.config.browser.launchOptions));\n return playwright[this.config.browser.browserName].connect(String(url));\n }\n\n protected override _extractRelevantConfig(): any {\n return {\n remoteEndpoint: this.config.browser.remoteEndpoint,\n browserName: this.config.browser.browserName,\n launchOptions: this.config.browser.launchOptions,\n };\n }\n\n protected override async _doCreateContext(browser: playwright.Browser): Promise<playwright.BrowserContext> {\n return browser.newContext();\n }\n}\n\nclass PersistentContextFactory implements BrowserContextFactory {\n readonly config: FullConfig;\n readonly name = 'persistent';\n readonly description = 'Create a new persistent browser context';\n\n private _userDataDirs = new Set<string>();\n\n constructor(config: FullConfig) {\n this.config = config;\n }\n\n async createContext(clientInfo: ClientInfo): Promise<BrowserContextFactoryResult> {\n const launchOptionsWithCdp = await injectCdpPort(this.config.browser);\n testDebug('create browser context (persistent)');\n const userDataDir = this.config.browser.userDataDir ?? await this._createUserDataDir(clientInfo);\n const tracesDir = await computeTracesDir(this.config, clientInfo);\n if (tracesDir && this.config.saveTrace)\n await startTraceServer(this.config, tracesDir);\n\n this._userDataDirs.add(userDataDir);\n testDebug('lock user data dir', userDataDir);\n\n const browserType = playwright[this.config.browser.browserName];\n for (let i = 0; i < 5; i++) {\n const launchPersistentOptions: LaunchOptions & BrowserContextOptions = {\n tracesDir,\n ...launchOptionsWithCdp,\n ...this.config.browser.contextOptions,\n handleSIGINT: false,\n handleSIGTERM: false,\n ignoreDefaultArgs: [\n '--disable-extensions',\n ],\n assistantMode: true,\n };\n try {\n const browserContext = await browserType.launchPersistentContext(userDataDir, launchPersistentOptions);\n await addInitScript(browserContext, this.config.browser.initScript);\n const close = (afterClose: () => Promise<void>) => this._closeBrowserContext(browserContext, userDataDir, afterClose);\n return { browserContext, close };\n } catch (error: any) {\n if (error.message.includes('Executable doesn\\'t exist'))\n throw new Error(`Browser specified in your config is not installed. Either install it (likely) or change the config.`);\n if (error.message.includes('ProcessSingleton') || error.message.includes('Invalid URL')) {\n // User data directory is already in use, try again.\n await new Promise(resolve => setTimeout(resolve, 1000));\n continue;\n }\n throw error;\n }\n }\n throw new Error(`Browser is already in use for ${userDataDir}, use --isolated to run multiple instances of the same browser`);\n }\n\n private async _closeBrowserContext(browserContext: playwright.BrowserContext, userDataDir: string, afterClose: () => Promise<void>) {\n testDebug('close browser context (persistent)');\n testDebug('release user data dir', userDataDir);\n await browserContext.close().catch(() => {});\n await afterClose();\n this._userDataDirs.delete(userDataDir);\n testDebug('close browser context complete (persistent)');\n }\n\n private async _createUserDataDir(clientInfo: ClientInfo) {\n const dir = process.env.PWMCP_PROFILES_DIR_FOR_TEST ?? registryDirectory;\n const browserToken = this.config.browser.launchOptions?.channel ?? this.config.browser?.browserName;\n // Hesitant putting hundreds of files into the user's workspace, so using it for hashing instead.\n const rootPath = firstRootPath(clientInfo);\n const rootPathToken = rootPath ? `-${createHash(rootPath)}` : '';\n const result = path.join(dir, `mcp-${browserToken}${rootPathToken}`);\n await fs.promises.mkdir(result, { recursive: true });\n return result;\n }\n}\n\nasync function injectCdpPort(browserConfig: FullConfig['browser']): Promise<any> {\n if (browserConfig.browserName === 'chromium') {\n const cdpPort = await findFreePort();\n return { ...browserConfig.launchOptions, cdpPort };\n }\n return browserConfig.launchOptions;\n}\n\nasync function findFreePort(): Promise<number> {\n return new Promise((resolve, reject) => {\n const server = net.createServer();\n server.listen(0, () => {\n const { port } = server.address() as net.AddressInfo;\n server.close(() => resolve(port));\n });\n server.on('error', reject);\n });\n}\n\nasync function startTraceServer(config: FullConfig, tracesDir: string): Promise<string | undefined> {\n if (!config.saveTrace)\n return;\n\n const server = await startTraceViewerServer();\n const urlPrefix = server.urlPrefix('human-readable');\n const url = urlPrefix + '/trace/index.html?trace=' + tracesDir + '/trace.json';\n // eslint-disable-next-line no-console\n console.error('\\nTrace viewer listening on ' + url);\n}\n\nfunction createHash(data: string): string {\n return crypto.createHash('sha256').update(data).digest('hex').slice(0, 7);\n}\n\nasync function addInitScript(browserContext: playwright.BrowserContext, initScript: string[] | undefined) {\n for (const scriptPath of initScript ?? [])\n await browserContext.addInitScript({ path: path.resolve(scriptPath) });\n}\n\nexport class SharedContextFactory implements BrowserContextFactory {\n private _contextPromise: Promise<BrowserContextFactoryResult> | undefined;\n private _baseFactory: BrowserContextFactory;\n private static _instance: SharedContextFactory | undefined;\n\n static create(config: FullConfig) {\n if (SharedContextFactory._instance)\n // throw new Error('SharedContextFactory already exists');\n return SharedContextFactory._instance;;\n const baseConfig = { ...config, sharedBrowserContext: false };\n const baseFactory = contextFactory(baseConfig);\n SharedContextFactory._instance = new SharedContextFactory(baseFactory);\n return SharedContextFactory._instance;\n }\n\n private constructor(baseFactory: BrowserContextFactory) {\n this._baseFactory = baseFactory;\n }\n\n async createContext(clientInfo: ClientInfo, abortSignal: AbortSignal, toolName: string | undefined): Promise<{ browserContext: playwright.BrowserContext, close: () => Promise<void> }> {\n if (!this._contextPromise) {\n testDebug('create shared browser context');\n this._contextPromise = this._baseFactory.createContext(clientInfo, abortSignal, toolName);\n }\n\n const { browserContext } = await this._contextPromise;\n testDebug(`shared context client connected`);\n return {\n browserContext,\n close: async () => {\n testDebug(`shared context client disconnected`);\n },\n };\n }\n\n static async dispose() {\n await SharedContextFactory._instance?._dispose();\n SharedContextFactory._instance = undefined;\n }\n\n private async _dispose() {\n const contextPromise = this._contextPromise;\n this._contextPromise = undefined;\n if (!contextPromise)\n return;\n const { close } = await contextPromise;\n await close(async () => {});\n }\n}\n\nasync function computeTracesDir(config: FullConfig, clientInfo: ClientInfo): Promise<string | undefined> {\n if (!config.saveTrace && !config.capabilities?.includes('tracing'))\n return;\n return await outputFile(config, clientInfo, `traces`, { origin: 'code', reason: 'Collecting trace' });\n}\n\n/**\n * Stable JSON stringify that sorts object keys alphabetically.\n * This ensures that objects with the same properties produce identical strings.\n */\nfunction stableStringify(obj: any): string {\n if (obj === null || obj === undefined) {\n return String(obj);\n }\n\n if (typeof obj !== 'object') {\n return JSON.stringify(obj);\n }\n\n if (Array.isArray(obj)) {\n return '[' + obj.map(item => stableStringify(item)).join(',') + ']';\n }\n\n // Sort object keys for stable output\n const sortedKeys = Object.keys(obj).sort();\n const pairs = sortedKeys.map(key => {\n return JSON.stringify(key) + ':' + stableStringify(obj[key]);\n });\n\n return '{' + pairs.join(',') + '}';\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_server", "crypto", "path", "fs", "net"]
|
|
7
|
+
}
|