@playwright/test 1.37.0-alpha-aug-8-2023 → 1.37.0-alpha-aug-9-2023
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/lib/common/config.js +5 -5
- package/lib/isomorphic/teleReceiver.js +2 -2
- package/lib/reporters/blob.js +1 -0
- package/lib/reporters/json.js +2 -2
- package/lib/reporters/merge.js +62 -29
- package/lib/reporters/teleEmitter.js +1 -1
- package/lib/transform/compilationCache.js +3 -2
- package/lib/transform/transform.js +1 -1
- package/package.json +2 -2
package/lib/common/config.js
CHANGED
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.defaultTimeout = exports.defaultReporter = exports.defaultGrep = exports.builtInReporters = exports.FullProjectInternal = exports.FullConfigInternal = void 0;
|
|
7
|
+
exports.getProjectId = getProjectId;
|
|
7
8
|
exports.takeFirst = takeFirst;
|
|
8
9
|
exports.toReporters = toReporters;
|
|
9
10
|
var _fs = _interopRequireDefault(require("fs"));
|
|
@@ -135,6 +136,7 @@ class FullConfigInternal {
|
|
|
135
136
|
const candidate = name + (i ? i : '');
|
|
136
137
|
if (usedNames.has(candidate)) continue;
|
|
137
138
|
p.id = candidate;
|
|
139
|
+
p.project.__projectId = p.id;
|
|
138
140
|
usedNames.add(candidate);
|
|
139
141
|
break;
|
|
140
142
|
}
|
|
@@ -143,9 +145,6 @@ class FullConfigInternal {
|
|
|
143
145
|
}
|
|
144
146
|
exports.FullConfigInternal = FullConfigInternal;
|
|
145
147
|
class FullProjectInternal {
|
|
146
|
-
static from(config) {
|
|
147
|
-
return config[projectInternalSymbol];
|
|
148
|
-
}
|
|
149
148
|
constructor(configDir, config, fullConfig, projectConfig, configCLIOverrides, throwawayArtifactsPath) {
|
|
150
149
|
this.project = void 0;
|
|
151
150
|
this.fullConfig = void 0;
|
|
@@ -179,7 +178,6 @@ class FullProjectInternal {
|
|
|
179
178
|
dependencies: projectConfig.dependencies || [],
|
|
180
179
|
teardown: projectConfig.teardown
|
|
181
180
|
};
|
|
182
|
-
this.project[projectInternalSymbol] = this;
|
|
183
181
|
this.fullyParallel = takeFirst(configCLIOverrides.fullyParallel, projectConfig.fullyParallel, config.fullyParallel, undefined);
|
|
184
182
|
this.expect = takeFirst(projectConfig.expect, config.expect, {});
|
|
185
183
|
this.respectGitIgnore = !projectConfig.testDir && !config.testDir;
|
|
@@ -252,4 +250,6 @@ exports.defaultGrep = defaultGrep;
|
|
|
252
250
|
const defaultReporter = process.env.CI ? 'dot' : 'list';
|
|
253
251
|
exports.defaultReporter = defaultReporter;
|
|
254
252
|
const configInternalSymbol = Symbol('configInternalSymbol');
|
|
255
|
-
|
|
253
|
+
function getProjectId(project) {
|
|
254
|
+
return project.__projectId;
|
|
255
|
+
}
|
|
@@ -97,7 +97,7 @@ class TeleReporterReceiver {
|
|
|
97
97
|
this._reporter.onConfigure(this._config);
|
|
98
98
|
}
|
|
99
99
|
_onProject(project) {
|
|
100
|
-
let projectSuite = this._rootSuite.suites.find(suite => suite.project().
|
|
100
|
+
let projectSuite = this._rootSuite.suites.find(suite => suite.project().__projectId === project.id);
|
|
101
101
|
if (!projectSuite) {
|
|
102
102
|
projectSuite = new TeleSuite(project.name, 'project');
|
|
103
103
|
this._rootSuite.suites.push(projectSuite);
|
|
@@ -219,7 +219,7 @@ class TeleReporterReceiver {
|
|
|
219
219
|
}
|
|
220
220
|
_parseProject(project) {
|
|
221
221
|
return {
|
|
222
|
-
|
|
222
|
+
__projectId: project.id,
|
|
223
223
|
metadata: project.metadata,
|
|
224
224
|
name: project.name,
|
|
225
225
|
outputDir: this._absolutePath(project.outputDir),
|
package/lib/reporters/blob.js
CHANGED
|
@@ -46,6 +46,7 @@ class BlobReporter extends _teleEmitter.TeleReporterEmitter {
|
|
|
46
46
|
var _config$shard;
|
|
47
47
|
const metadata = {
|
|
48
48
|
version: currentBlobReportVersion,
|
|
49
|
+
userAgent: (0, _utils.getUserAgent)(),
|
|
49
50
|
name: process.env.PWTEST_BLOB_REPORT_NAME,
|
|
50
51
|
shard: (_config$shard = config.shard) !== null && _config$shard !== void 0 ? _config$shard : undefined
|
|
51
52
|
};
|
package/lib/reporters/json.js
CHANGED
|
@@ -67,7 +67,7 @@ class JSONReporter extends _empty.default {
|
|
|
67
67
|
repeatEach: project.repeatEach,
|
|
68
68
|
retries: project.retries,
|
|
69
69
|
metadata: project.metadata,
|
|
70
|
-
id: _config.
|
|
70
|
+
id: (0, _config.getProjectId)(project),
|
|
71
71
|
name: project.name,
|
|
72
72
|
testDir: toPosixPath(project.testDir),
|
|
73
73
|
testIgnore: serializePatterns(project.testIgnore),
|
|
@@ -83,7 +83,7 @@ class JSONReporter extends _empty.default {
|
|
|
83
83
|
_mergeSuites(suites) {
|
|
84
84
|
const fileSuites = new _utils.MultiMap();
|
|
85
85
|
for (const projectSuite of suites) {
|
|
86
|
-
const projectId = _config.
|
|
86
|
+
const projectId = (0, _config.getProjectId)(projectSuite.project());
|
|
87
87
|
const projectName = projectSuite.project().name;
|
|
88
88
|
for (const fileSuite of projectSuite.suites) {
|
|
89
89
|
const file = fileSuite.location.file;
|
package/lib/reporters/merge.js
CHANGED
|
@@ -34,6 +34,7 @@ async function createMergedReport(config, dir, reporterDescriptions) {
|
|
|
34
34
|
const reporters = await (0, _reporters.createReporters)(config, 'merge', reporterDescriptions);
|
|
35
35
|
const multiplexer = new _multiplexer.Multiplexer(reporters);
|
|
36
36
|
const receiver = new _teleReceiver.TeleReporterReceiver(_path.default.sep, multiplexer, false, config.config);
|
|
37
|
+
const stringPool = new _stringInternPool.StringInternPool();
|
|
37
38
|
let printStatus = () => {};
|
|
38
39
|
if (!multiplexer.printsToStdio()) {
|
|
39
40
|
printStatus = printStatusToStdout;
|
|
@@ -41,14 +42,28 @@ async function createMergedReport(config, dir, reporterDescriptions) {
|
|
|
41
42
|
}
|
|
42
43
|
const shardFiles = await sortedShardFiles(dir);
|
|
43
44
|
if (shardFiles.length === 0) throw new Error(`No report files found in ${dir}`);
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
const eventData = await mergeEvents(dir, shardFiles, stringPool, printStatus);
|
|
46
|
+
printStatus(`processing test events`);
|
|
47
|
+
const dispatchEvents = async events => {
|
|
48
|
+
for (const event of events) {
|
|
49
|
+
if (event.method === 'onEnd') printStatus(`building final report`);
|
|
50
|
+
await receiver.dispatch(event);
|
|
51
|
+
if (event.method === 'onEnd') printStatus(`finished building report`);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
await dispatchEvents(eventData.prologue);
|
|
55
|
+
for (const {
|
|
56
|
+
reportFile,
|
|
57
|
+
idsPatcher
|
|
58
|
+
} of eventData.reports) {
|
|
59
|
+
const reportJsonl = await _fs.default.promises.readFile(reportFile);
|
|
60
|
+
const events = parseTestEvents(reportJsonl);
|
|
61
|
+
new _stringInternPool.JsonStringInternalizer(stringPool).traverse(events);
|
|
62
|
+
idsPatcher.patchEvents(events);
|
|
63
|
+
patchAttachmentPaths(events, dir);
|
|
64
|
+
await dispatchEvents(events);
|
|
51
65
|
}
|
|
66
|
+
await dispatchEvents(eventData.epilogue);
|
|
52
67
|
}
|
|
53
68
|
function patchAttachmentPaths(events, resourceDir) {
|
|
54
69
|
for (const event of events) {
|
|
@@ -59,37 +74,43 @@ function patchAttachmentPaths(events, resourceDir) {
|
|
|
59
74
|
}
|
|
60
75
|
}
|
|
61
76
|
}
|
|
62
|
-
|
|
63
|
-
|
|
77
|
+
const commonEventNames = ['onBlobReportMetadata', 'onConfigure', 'onProject', 'onBegin', 'onEnd'];
|
|
78
|
+
const commonEvents = new Set(commonEventNames);
|
|
79
|
+
const commonEventRegex = new RegExp(`${commonEventNames.join('|')}`);
|
|
80
|
+
function parseCommonEvents(reportJsonl) {
|
|
81
|
+
return reportJsonl.toString().split('\n').filter(line => commonEventRegex.test(line)) // quick filter
|
|
82
|
+
.map(line => JSON.parse(line)).filter(event => commonEvents.has(event.method));
|
|
83
|
+
}
|
|
84
|
+
function parseTestEvents(reportJsonl) {
|
|
85
|
+
return reportJsonl.toString().split('\n').filter(line => line.length).map(line => JSON.parse(line)).filter(event => !commonEvents.has(event.method));
|
|
64
86
|
}
|
|
65
|
-
async function extractAndParseReports(dir, shardFiles,
|
|
87
|
+
async function extractAndParseReports(dir, shardFiles, internalizer, printStatus) {
|
|
66
88
|
const shardEvents = [];
|
|
67
89
|
await _fs.default.promises.mkdir(_path.default.join(dir, 'resources'), {
|
|
68
90
|
recursive: true
|
|
69
91
|
});
|
|
70
|
-
const internalizer = new _stringInternPool.JsonStringInternalizer(stringPool);
|
|
71
92
|
for (const file of shardFiles) {
|
|
72
93
|
const absolutePath = _path.default.join(dir, file);
|
|
73
94
|
printStatus(`extracting: ${(0, _util.relativeFilePath)(absolutePath)}`);
|
|
74
95
|
const zipFile = new _utils.ZipFile(absolutePath);
|
|
75
96
|
const entryNames = await zipFile.entries();
|
|
76
97
|
for (const entryName of entryNames.sort()) {
|
|
98
|
+
const fileName = _path.default.join(dir, entryName);
|
|
77
99
|
const content = await zipFile.read(entryName);
|
|
78
100
|
if (entryName.endsWith('.jsonl')) {
|
|
79
|
-
const parsedEvents =
|
|
101
|
+
const parsedEvents = parseCommonEvents(content);
|
|
80
102
|
// Passing reviver to JSON.parse doesn't work, as the original strings
|
|
81
103
|
// keep beeing used. To work around that we traverse the parsed events
|
|
82
104
|
// as a post-processing step.
|
|
83
105
|
internalizer.traverse(parsedEvents);
|
|
84
106
|
shardEvents.push({
|
|
85
107
|
file,
|
|
108
|
+
localPath: fileName,
|
|
86
109
|
metadata: findMetadata(parsedEvents, file),
|
|
87
110
|
parsedEvents
|
|
88
111
|
});
|
|
89
|
-
} else {
|
|
90
|
-
const fileName = _path.default.join(dir, entryName);
|
|
91
|
-
await _fs.default.promises.writeFile(fileName, content);
|
|
92
112
|
}
|
|
113
|
+
await _fs.default.promises.writeFile(fileName, content);
|
|
93
114
|
}
|
|
94
115
|
zipFile.close();
|
|
95
116
|
}
|
|
@@ -102,13 +123,12 @@ function findMetadata(events, file) {
|
|
|
102
123
|
if (metadata.version > _blob.currentBlobReportVersion) throw new Error(`Blob report ${file} was created with a newer version of Playwright.`);
|
|
103
124
|
return metadata;
|
|
104
125
|
}
|
|
105
|
-
async function mergeEvents(dir, shardReportFiles, printStatus) {
|
|
106
|
-
const
|
|
107
|
-
const events = [];
|
|
126
|
+
async function mergeEvents(dir, shardReportFiles, stringPool, printStatus) {
|
|
127
|
+
const internalizer = new _stringInternPool.JsonStringInternalizer(stringPool);
|
|
108
128
|
const configureEvents = [];
|
|
109
129
|
const projectEvents = [];
|
|
110
130
|
const endEvents = [];
|
|
111
|
-
const blobs = await extractAndParseReports(dir, shardReportFiles,
|
|
131
|
+
const blobs = await extractAndParseReports(dir, shardReportFiles, internalizer, printStatus);
|
|
112
132
|
// Sort by (report name; shard; file name), so that salt generation below is deterministic when:
|
|
113
133
|
// - report names are unique;
|
|
114
134
|
// - report names are missing;
|
|
@@ -125,28 +145,41 @@ async function mergeEvents(dir, shardReportFiles, printStatus) {
|
|
|
125
145
|
});
|
|
126
146
|
const saltSet = new Set();
|
|
127
147
|
printStatus(`merging events`);
|
|
148
|
+
const reports = [];
|
|
128
149
|
for (const {
|
|
129
150
|
file,
|
|
130
151
|
parsedEvents,
|
|
131
|
-
metadata
|
|
152
|
+
metadata,
|
|
153
|
+
localPath
|
|
132
154
|
} of blobs) {
|
|
133
155
|
// Generate unique salt for each blob.
|
|
134
156
|
const sha1 = (0, _utils.calculateSha1)(metadata.name || _path.default.basename(file)).substring(0, 16);
|
|
135
157
|
let salt = sha1;
|
|
136
158
|
for (let i = 0; saltSet.has(salt); i++) salt = sha1 + '-' + i;
|
|
137
159
|
saltSet.add(salt);
|
|
138
|
-
new IdsPatcher(stringPool, metadata.name, salt)
|
|
160
|
+
const idsPatcher = new IdsPatcher(stringPool, metadata.name, salt);
|
|
161
|
+
idsPatcher.patchEvents(parsedEvents);
|
|
139
162
|
for (const event of parsedEvents) {
|
|
140
|
-
if (event.method === 'onConfigure') configureEvents.push(event);else if (event.method === 'onProject') projectEvents.push(event);else if (event.method === 'onEnd') endEvents.push(event);
|
|
163
|
+
if (event.method === 'onConfigure') configureEvents.push(event);else if (event.method === 'onProject') projectEvents.push(event);else if (event.method === 'onEnd') endEvents.push(event);
|
|
141
164
|
}
|
|
165
|
+
|
|
166
|
+
// Save information about the reports to stream their test events later.
|
|
167
|
+
reports.push({
|
|
168
|
+
idsPatcher,
|
|
169
|
+
reportFile: localPath
|
|
170
|
+
});
|
|
142
171
|
}
|
|
143
|
-
return
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
172
|
+
return {
|
|
173
|
+
prologue: [mergeConfigureEvents(configureEvents), ...projectEvents, {
|
|
174
|
+
method: 'onBegin',
|
|
175
|
+
params: undefined
|
|
176
|
+
}],
|
|
177
|
+
reports,
|
|
178
|
+
epilogue: [mergeEndEvents(endEvents), {
|
|
179
|
+
method: 'onExit',
|
|
180
|
+
params: undefined
|
|
181
|
+
}]
|
|
182
|
+
};
|
|
150
183
|
}
|
|
151
184
|
function mergeConfigureEvents(configureEvents) {
|
|
152
185
|
if (!configureEvents.length) throw new Error('No configure events found');
|
|
@@ -160,7 +160,7 @@ class TeleReporterEmitter {
|
|
|
160
160
|
_serializeProject(suite) {
|
|
161
161
|
const project = suite.project();
|
|
162
162
|
const report = {
|
|
163
|
-
id: _config.
|
|
163
|
+
id: (0, _config.getProjectId)(project),
|
|
164
164
|
metadata: project.metadata,
|
|
165
165
|
name: project.name,
|
|
166
166
|
outputDir: this._relativePath(project.outputDir),
|
|
@@ -19,6 +19,7 @@ var _fs = _interopRequireDefault(require("fs"));
|
|
|
19
19
|
var _os = _interopRequireDefault(require("os"));
|
|
20
20
|
var _path = _interopRequireDefault(require("path"));
|
|
21
21
|
var _utilsBundle = require("../utilsBundle");
|
|
22
|
+
var _utils = require("playwright-core/lib/utils");
|
|
22
23
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
23
24
|
/**
|
|
24
25
|
* Copyright (c) Microsoft Corporation.
|
|
@@ -95,8 +96,8 @@ function getFromCompilationCache(filename, hash, moduleUrl) {
|
|
|
95
96
|
_fs.default.mkdirSync(_path.default.dirname(cachePath), {
|
|
96
97
|
recursive: true
|
|
97
98
|
});
|
|
98
|
-
if (map)
|
|
99
|
-
|
|
99
|
+
if (map) (0, _utils.writeFileSyncAtomic)(sourceMapPath, JSON.stringify(map), 'utf8');
|
|
100
|
+
(0, _utils.writeFileSyncAtomic)(codePath, code, 'utf8');
|
|
100
101
|
_innerAddToCompilationCache(filename, {
|
|
101
102
|
codePath,
|
|
102
103
|
sourceMapPath,
|
|
@@ -144,7 +144,7 @@ function transformHook(originalCode, filename, moduleUrl) {
|
|
|
144
144
|
cachedCode,
|
|
145
145
|
addToCache
|
|
146
146
|
} = (0, _compilationCache.getFromCompilationCache)(filename, hash, moduleUrl);
|
|
147
|
-
if (cachedCode) return cachedCode;
|
|
147
|
+
if (cachedCode !== undefined) return cachedCode;
|
|
148
148
|
|
|
149
149
|
// We don't use any browserslist data, but babel checks it anyway.
|
|
150
150
|
// Silence the annoying warning.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@playwright/test",
|
|
3
|
-
"version": "1.37.0-alpha-aug-
|
|
3
|
+
"version": "1.37.0-alpha-aug-9-2023",
|
|
4
4
|
"description": "A high-level API to automate web browsers",
|
|
5
5
|
"repository": "github:Microsoft/playwright",
|
|
6
6
|
"homepage": "https://playwright.dev",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"license": "Apache-2.0",
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@types/node": "*",
|
|
44
|
-
"playwright-core": "1.37.0-alpha-aug-
|
|
44
|
+
"playwright-core": "1.37.0-alpha-aug-9-2023"
|
|
45
45
|
},
|
|
46
46
|
"optionalDependencies": {
|
|
47
47
|
"fsevents": "2.3.2"
|