playwright
Advanced tools
Comparing version
@@ -140,3 +140,3 @@ "use strict"; | ||
const location = this._absoluteLocation(payload.location); | ||
const step = new TeleTestStep(payload, parentStep, location); | ||
const step = new TeleTestStep(payload, parentStep, location, result); | ||
if (parentStep) parentStep.steps.push(step);else result.steps.push(step); | ||
@@ -151,2 +151,3 @@ result._stepMap.set(payload.id, step); | ||
const step = result._stepMap.get(payload.id); | ||
step._endPayload = payload; | ||
step.duration = payload.duration; | ||
@@ -365,3 +366,3 @@ step.error = payload.error; | ||
class TeleTestStep { | ||
constructor(payload, parentStep, location) { | ||
constructor(payload, parentStep, location, result) { | ||
this.title = void 0; | ||
@@ -373,2 +374,5 @@ this.category = void 0; | ||
this.steps = []; | ||
this.error = void 0; | ||
this._result = void 0; | ||
this._endPayload = void 0; | ||
this._startTime = 0; | ||
@@ -380,2 +384,3 @@ this.title = payload.title; | ||
this._startTime = payload.startTime; | ||
this._result = result; | ||
} | ||
@@ -393,2 +398,6 @@ titlePath() { | ||
} | ||
get attachments() { | ||
var _this$_endPayload$att, _this$_endPayload; | ||
return (_this$_endPayload$att = (_this$_endPayload = this._endPayload) === null || _this$_endPayload === void 0 || (_this$_endPayload = _this$_endPayload.attachments) === null || _this$_endPayload === void 0 ? void 0 : _this$_endPayload.map(index => this._result.attachments[index])) !== null && _this$_endPayload$att !== void 0 ? _this$_endPayload$att : []; | ||
} | ||
} | ||
@@ -395,0 +404,0 @@ class TeleTestResult { |
@@ -490,3 +490,3 @@ "use strict"; | ||
retry: result.retry, | ||
steps: dedupeSteps(result.steps).map(s => this._createTestStep(s)), | ||
steps: dedupeSteps(result.steps).map(s => this._createTestStep(s, result)), | ||
errors: (0, _base.formatResultFailure)(test, result, '', true).map(error => error.message), | ||
@@ -497,3 +497,3 @@ status: result.status, | ||
} | ||
_createTestStep(dedupedStep) { | ||
_createTestStep(dedupedStep, result) { | ||
var _step$error; | ||
@@ -505,7 +505,12 @@ const { | ||
} = dedupedStep; | ||
const result = { | ||
const testStep = { | ||
title: step.title, | ||
startTime: step.startTime.toISOString(), | ||
duration, | ||
steps: dedupeSteps(step.steps).map(s => this._createTestStep(s)), | ||
steps: dedupeSteps(step.steps).map(s => this._createTestStep(s, result)), | ||
attachments: step.attachments.map(s => { | ||
const index = result.attachments.indexOf(s); | ||
if (index === -1) throw new Error('Unexpected, attachment not found'); | ||
return index; | ||
}), | ||
location: this._relativeLocation(step.location), | ||
@@ -515,4 +520,4 @@ error: (_step$error = step.error) === null || _step$error === void 0 ? void 0 : _step$error.message, | ||
}; | ||
if (step.location) this._stepsInFile.set(step.location.file, result); | ||
return result; | ||
if (step.location) this._stepsInFile.set(step.location.file, testStep); | ||
return testStep; | ||
} | ||
@@ -519,0 +524,0 @@ _relativeLocation(location) { |
@@ -105,3 +105,3 @@ "use strict"; | ||
resultId: result[this._idSymbol], | ||
step: this._serializeStepEnd(step) | ||
step: this._serializeStepEnd(step, result) | ||
} | ||
@@ -249,7 +249,8 @@ }); | ||
} | ||
_serializeStepEnd(step) { | ||
_serializeStepEnd(step, result) { | ||
return { | ||
id: step[this._idSymbol], | ||
duration: step.duration, | ||
error: step.error | ||
error: step.error, | ||
attachments: step.attachments.map(a => result.attachments.indexOf(a)) | ||
}; | ||
@@ -256,0 +257,0 @@ } |
@@ -324,2 +324,3 @@ "use strict"; | ||
steps: [], | ||
attachments: [], | ||
location: params.location | ||
@@ -368,2 +369,7 @@ }; | ||
data.result.attachments.push(attachment); | ||
if (params.stepId) { | ||
var _this$_reporter$onStd4, _this$_reporter8; | ||
const step = data.steps.get(params.stepId); | ||
if (step) step.attachments.push(attachment);else (_this$_reporter$onStd4 = (_this$_reporter8 = this._reporter).onStdErr) === null || _this$_reporter$onStd4 === void 0 || _this$_reporter$onStd4.call(_this$_reporter8, 'Internal error: step id not found: ' + params.stepId); | ||
} | ||
} | ||
@@ -377,5 +383,5 @@ _failTestWithErrors(test, errors) { | ||
} else { | ||
var _this$_reporter$onTes2, _this$_reporter8; | ||
var _this$_reporter$onTes2, _this$_reporter9; | ||
result = test._appendTestResult(); | ||
(_this$_reporter$onTes2 = (_this$_reporter8 = this._reporter).onTestBegin) === null || _this$_reporter$onTes2 === void 0 || _this$_reporter$onTes2.call(_this$_reporter8, test, result); | ||
(_this$_reporter$onTes2 = (_this$_reporter9 = this._reporter).onTestBegin) === null || _this$_reporter$onTes2 === void 0 || _this$_reporter$onTes2.call(_this$_reporter9, test, result); | ||
} | ||
@@ -402,4 +408,4 @@ result.errors = [...errors]; | ||
for (const error of errors) { | ||
var _this$_reporter$onErr2, _this$_reporter9; | ||
(_this$_reporter$onErr2 = (_this$_reporter9 = this._reporter).onError) === null || _this$_reporter$onErr2 === void 0 || _this$_reporter$onErr2.call(_this$_reporter9, error); | ||
var _this$_reporter$onErr2, _this$_reporter10; | ||
(_this$_reporter$onErr2 = (_this$_reporter10 = this._reporter).onError) === null || _this$_reporter$onErr2 === void 0 || _this$_reporter$onErr2.call(_this$_reporter10, error); | ||
} | ||
@@ -524,5 +530,5 @@ } | ||
for (const test of this._job.tests) { | ||
var _this$_reporter$onTes3, _this$_reporter10; | ||
var _this$_reporter$onTes3, _this$_reporter11; | ||
const result = test._appendTestResult(); | ||
(_this$_reporter$onTes3 = (_this$_reporter10 = this._reporter).onTestBegin) === null || _this$_reporter$onTes3 === void 0 || _this$_reporter$onTes3.call(_this$_reporter10, test, result); | ||
(_this$_reporter$onTes3 = (_this$_reporter11 = this._reporter).onTestBegin) === null || _this$_reporter$onTes3 === void 0 || _this$_reporter$onTes3.call(_this$_reporter11, test, result); | ||
result.status = 'skipped'; | ||
@@ -539,10 +545,10 @@ this._reportTestEnd(test, result); | ||
_reportTestEnd(test, result) { | ||
var _this$_reporter$onTes4, _this$_reporter11; | ||
(_this$_reporter$onTes4 = (_this$_reporter11 = this._reporter).onTestEnd) === null || _this$_reporter$onTes4 === void 0 || _this$_reporter$onTes4.call(_this$_reporter11, test, result); | ||
var _this$_reporter$onTes4, _this$_reporter12; | ||
(_this$_reporter$onTes4 = (_this$_reporter12 = this._reporter).onTestEnd) === null || _this$_reporter$onTes4 === void 0 || _this$_reporter$onTes4.call(_this$_reporter12, test, result); | ||
const hadMaxFailures = this._failureTracker.hasReachedMaxFailures(); | ||
this._failureTracker.onTestEnd(test, result); | ||
if (this._failureTracker.hasReachedMaxFailures()) { | ||
var _this$_reporter$onErr3, _this$_reporter12; | ||
var _this$_reporter$onErr3, _this$_reporter13; | ||
this._stopCallback(); | ||
if (!hadMaxFailures) (_this$_reporter$onErr3 = (_this$_reporter12 = this._reporter).onError) === null || _this$_reporter$onErr3 === void 0 || _this$_reporter$onErr3.call(_this$_reporter12, { | ||
if (!hadMaxFailures) (_this$_reporter$onErr3 = (_this$_reporter13 = this._reporter).onError) === null || _this$_reporter$onErr3 === void 0 || _this$_reporter$onErr3.call(_this$_reporter13, { | ||
message: _utilsBundle.colors.red(`Testing stopped early after ${this._failureTracker.maxFailures()} maximum allowed failures.`) | ||
@@ -549,0 +555,0 @@ }); |
@@ -77,2 +77,3 @@ "use strict"; | ||
this._steps = []; | ||
this._stepMap = new Map(); | ||
this._onDidFinishTestFunction = void 0; | ||
@@ -148,3 +149,6 @@ this._hasNonRetriableError = false; | ||
this.attachments.push = (...attachments) => { | ||
for (const a of attachments) this._attach(a.name, a); | ||
for (const a of attachments) { | ||
var _this$_expectStepId, _this$_parentStep; | ||
this._attach(a, (_this$_expectStepId = this._expectStepId()) !== null && _this$_expectStepId !== void 0 ? _this$_expectStepId : (_this$_parentStep = this._parentStep()) === null || _this$_parentStep === void 0 ? void 0 : _this$_parentStep.stepId); | ||
} | ||
return this.attachments.length; | ||
@@ -181,2 +185,10 @@ }; | ||
} | ||
_parentStep() { | ||
var _zones$zoneData; | ||
return (_zones$zoneData = _utils.zones.zoneData('stepZone')) !== null && _zones$zoneData !== void 0 ? _zones$zoneData : this._findLastStageStep(this._steps); // If no parent step on stack, assume the current stage as parent. | ||
} | ||
_expectStepId() { | ||
var _zones$zoneData2; | ||
return (_zones$zoneData2 = _utils.zones.zoneData('expectZone')) === null || _zones$zoneData2 === void 0 ? void 0 : _zones$zoneData2.stepId; | ||
} | ||
_addStep(data, parentStep) { | ||
@@ -189,7 +201,3 @@ var _parentStep, _parentStep2; | ||
} else { | ||
if (!parentStep) parentStep = _utils.zones.zoneData('stepZone'); | ||
if (!parentStep) { | ||
// If no parent step on stack, assume the current stage as parent. | ||
parentStep = this._findLastStageStep(this._steps); | ||
} | ||
if (!parentStep) parentStep = this._parentStep(); | ||
} | ||
@@ -203,2 +211,3 @@ const filteredStack = (0, _util.filteredStackTrace)((0, _utils.captureRawStack)()); | ||
data.location = data.location || filteredStack[0]; | ||
const attachmentIndices = []; | ||
const step = { | ||
@@ -208,2 +217,3 @@ stepId, | ||
steps: [], | ||
attachmentIndices, | ||
complete: result => { | ||
@@ -244,3 +254,4 @@ if (step.endWallTime) return; | ||
} : undefined; | ||
this._tracing.appendAfterActionForStep(stepId, errorForTrace, result.attachments); | ||
const attachments = attachmentIndices.map(i => this.attachments[i]); | ||
this._tracing.appendAfterActionForStep(stepId, errorForTrace, attachments); | ||
} | ||
@@ -250,2 +261,3 @@ }; | ||
parentStepList.push(step); | ||
this._stepMap.set(stepId, step); | ||
const payload = { | ||
@@ -341,6 +353,2 @@ testId: this.testId, | ||
async attach(name, options = {}) { | ||
this._attach(name, await (0, _util.normalizeAndSaveAttachment)(this.outputPath(), name, options)); | ||
} | ||
_attach(name, attachment) { | ||
var _attachment$body; | ||
const step = this._addStep({ | ||
@@ -350,3 +358,17 @@ title: `attach "${name}"`, | ||
}); | ||
this._attachmentsPush(attachment); | ||
this._attach(await (0, _util.normalizeAndSaveAttachment)(this.outputPath(), name, options), step.stepId); | ||
step.complete({}); | ||
} | ||
_attach(attachment, stepId) { | ||
var _attachment$body; | ||
const index = this._attachmentsPush(attachment) - 1; | ||
if (stepId) { | ||
this._stepMap.get(stepId).attachmentIndices.push(index); | ||
} else { | ||
var _this$_findLastStageS; | ||
// trace viewer has no means of representing attachments outside of a step, so we create an artificial action | ||
const callId = `attach@${++this._lastStepId}`; | ||
this._tracing.appendBeforeActionForStep(callId, (_this$_findLastStageS = this._findLastStageStep(this._steps)) === null || _this$_findLastStageS === void 0 ? void 0 : _this$_findLastStageS.stepId, `attach "${attachment.name}"`, undefined, []); | ||
this._tracing.appendAfterActionForStep(callId, undefined, [attachment]); | ||
} | ||
this._onAttach({ | ||
@@ -357,7 +379,5 @@ testId: this.testId, | ||
path: attachment.path, | ||
body: (_attachment$body = attachment.body) === null || _attachment$body === void 0 ? void 0 : _attachment$body.toString('base64') | ||
body: (_attachment$body = attachment.body) === null || _attachment$body === void 0 ? void 0 : _attachment$body.toString('base64'), | ||
stepId | ||
}); | ||
step.complete({ | ||
attachments: [attachment] | ||
}); | ||
} | ||
@@ -364,0 +384,0 @@ outputPath(...pathSegments) { |
{ | ||
"name": "playwright", | ||
"version": "1.50.0-alpha-2025-01-02", | ||
"version": "1.50.0-alpha-2025-01-03", | ||
"description": "A high-level API to automate web browsers", | ||
@@ -59,3 +59,3 @@ "repository": { | ||
"dependencies": { | ||
"playwright-core": "1.50.0-alpha-2025-01-02" | ||
"playwright-core": "1.50.0-alpha-2025-01-03" | ||
}, | ||
@@ -62,0 +62,0 @@ "optionalDependencies": { |
@@ -695,2 +695,29 @@ // This file is generated by /utils/generate_types/index.js | ||
/** | ||
* The list of files or buffers attached in the step execution through | ||
* [testInfo.attach(name[, options])](https://playwright.dev/docs/api/class-testinfo#test-info-attach). | ||
*/ | ||
attachments: Array<{ | ||
/** | ||
* Attachment name. | ||
*/ | ||
name: string; | ||
/** | ||
* Content type of this attachment to properly present in the report, for example `'application/json'` or | ||
* `'image/png'`. | ||
*/ | ||
contentType: string; | ||
/** | ||
* Optional path on the filesystem to the attached file. | ||
*/ | ||
path?: string; | ||
/** | ||
* Optional attachment body used instead of a file. | ||
*/ | ||
body?: Buffer; | ||
}>; | ||
/** | ||
* Step category to differentiate steps with different origin and verbosity. Built-in categories are: | ||
@@ -697,0 +724,0 @@ * - `hook` for fixtures and hooks initialization and teardown |
3170197
0.11%36187
0.18%+ Added
- Removed