88 lines
4.7 KiB
JavaScript
88 lines
4.7 KiB
JavaScript
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.attachErrorPrompts = attachErrorPrompts;
|
|
var fs = _interopRequireWildcard(require("fs"));
|
|
var path = _interopRequireWildcard(require("path"));
|
|
var _utils = require("playwright-core/lib/utils");
|
|
var _util = require("./util");
|
|
var _babelBundle = require("./transform/babelBundle");
|
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
/**
|
|
* Copyright (c) Microsoft Corporation.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the 'License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
async function attachErrorPrompts(testInfo, sourceCache, ariaSnapshot) {
|
|
if (process.env.PLAYWRIGHT_NO_COPY_PROMPT) return;
|
|
const meaningfulSingleLineErrors = new Set(testInfo.errors.filter(e => e.message && !e.message.includes('\n')).map(e => e.message));
|
|
for (const error of testInfo.errors) {
|
|
for (const singleLineError of meaningfulSingleLineErrors.keys()) {
|
|
var _error$message;
|
|
if ((_error$message = error.message) !== null && _error$message !== void 0 && _error$message.includes(singleLineError)) meaningfulSingleLineErrors.delete(singleLineError);
|
|
}
|
|
}
|
|
for (const [index, error] of testInfo.errors.entries()) {
|
|
if (!error.message) return;
|
|
if (testInfo.attachments.find(a => a.name === `_prompt-${index}`)) continue;
|
|
|
|
// Skip errors that are just a single line - they are likely to already be the error message.
|
|
if (!error.message.includes('\n') && !meaningfulSingleLineErrors.has(error.message)) continue;
|
|
const metadata = testInfo.config.metadata;
|
|
const promptParts = [`# Instructions`, '', `- Following Playwright test failed.`, `- Explain why, be concise, respect Playwright best practices.`, `- Provide a snippet of code with the fix, if possible.`, '', `# Test info`, '', `- Name: ${testInfo.titlePath.slice(1).join(' >> ')}`, `- Location: ${testInfo.file}:${testInfo.line}:${testInfo.column}`, '', '# Error details', '', '```', (0, _util.stripAnsiEscapes)(error.stack || error.message || ''), '```'];
|
|
if (ariaSnapshot) {
|
|
promptParts.push('', '# Page snapshot', '', '```yaml', ariaSnapshot, '```');
|
|
}
|
|
const parsedError = error.stack ? (0, _utils.parseErrorStack)(error.stack, path.sep) : undefined;
|
|
const inlineMessage = (0, _util.stripAnsiEscapes)((parsedError === null || parsedError === void 0 ? void 0 : parsedError.message) || error.message || '').split('\n')[0];
|
|
const location = (parsedError === null || parsedError === void 0 ? void 0 : parsedError.location) || {
|
|
file: testInfo.file,
|
|
line: testInfo.line,
|
|
column: testInfo.column
|
|
};
|
|
const source = await loadSource(location.file, sourceCache);
|
|
const codeFrame = (0, _babelBundle.codeFrameColumns)(source, {
|
|
start: {
|
|
line: location.line,
|
|
column: location.column
|
|
}
|
|
}, {
|
|
highlightCode: false,
|
|
linesAbove: 100,
|
|
linesBelow: 100,
|
|
message: inlineMessage || undefined
|
|
});
|
|
promptParts.push('', '# Test source', '', '```ts', codeFrame, '```');
|
|
if (metadata.gitDiff) {
|
|
promptParts.push('', '# Local changes', '', '```diff', metadata.gitDiff, '```');
|
|
}
|
|
testInfo._attach({
|
|
name: `_prompt-${index}`,
|
|
contentType: 'text/markdown',
|
|
body: Buffer.from(promptParts.join('\n'))
|
|
}, undefined);
|
|
}
|
|
}
|
|
async function loadSource(file, sourceCache) {
|
|
let source = sourceCache.get(file);
|
|
if (!source) {
|
|
// A mild race is Ok here.
|
|
source = await fs.promises.readFile(file, 'utf8');
|
|
sourceCache.set(file, source);
|
|
}
|
|
return source;
|
|
} |