@qartisan/playwright-loupe 0.0.1 → 0.0.2
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/CHANGELOG.md +7 -1
- package/README.md +1 -1
- package/dist/core/categories.js +27 -0
- package/dist/core/signature.js +14 -3
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,7 +4,13 @@ All notable changes to this project are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Before 1.0, minor versions may contain breaking changes. The JSON report has its own version (`schemaVersion`), see [`docs/schema/v1.md`](docs/schema/v1.md#versioning-policy).
|
|
6
6
|
|
|
7
|
-
## [
|
|
7
|
+
## [0.0.2] - 2026-10-15
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- **Error signatures change: failures are grouped differently from 0.0.1.** Normalization now also replaces e-mail addresses with `<email>` and cuid-like and nanoid-like identifiers (20+ characters mixing letters and digits) with `<id>`, so the same failure for different users or records gets one signature. A signature computed by 0.0.1 for a message containing such values no longer matches. The JSON shape is unchanged: `schemaVersion` stays `1`. See [Error signature](docs/schema/v1.md#error-signature).
|
|
12
|
+
- **New built-in error categories**, evaluated after "Locator not found" and before "Network", "Assertion" and "Timeout": **Rate limited** (`Too Many Requests`, `rate limit`, a 429 in an HTTP context such as `status 429`, `HTTP 429` or `Response status: 429`) and **Server error** (a 500–599 status in the same contexts, or with its reason phrase such as `502 Bad Gateway`). Errors from `failOnStatusCode` and failed `expect(response).toBeOK()` that were "Uncategorized" or "Assertion" now land in these categories. A bare number (`429ms`, `Received: 500`) does not match. See [Error categories](docs/schema/v1.md#error-categories).
|
|
13
|
+
- The package description now lists only what exists today.
|
|
8
14
|
|
|
9
15
|
## [0.0.1] - 2026-10-13
|
|
10
16
|
|
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# playwright-loupe
|
|
2
|
-
Loupe —
|
|
2
|
+
Loupe — an HTML reporter for Playwright: run summary, tests grouped by project and suite, dimensions from tags and annotations, and detailed failures with every attempt, error categories and signatures. Native Playwright APIs only.
|
|
3
3
|
|
|
4
4
|
> **Status: work in progress — the JSON schema will change before 1.0.**
|
|
5
5
|
|
package/dist/core/categories.js
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
const ALL_TARGETS = ['message', 'stack', 'step'];
|
|
2
2
|
export const UNCATEGORIZED_COLOR = '#6b7280';
|
|
3
|
+
/**
|
|
4
|
+
* An HTTP status in context: `status 429`, `status code: 429`, `"status": 429`,
|
|
5
|
+
* `statusCode=429`, `HTTP 429`, `HTTP/1.1 429`, `Response status: 429`, or
|
|
6
|
+
* `← 429`, the response line of Playwright's fetch log.
|
|
7
|
+
*/
|
|
8
|
+
function httpStatus(code) {
|
|
9
|
+
return new RegExp(`(?:\\b(?:status(?:[ _]?code)?["']?\\s*[:=]?|HTTP(?:/\\d(?:\\.\\d)?)?:?)|\u2190)\\s*${code}(?!\\w|\\.\\d)`, 'i');
|
|
10
|
+
}
|
|
3
11
|
export const BUILT_IN_RULES = [
|
|
4
12
|
{
|
|
5
13
|
// Before "Assertion" and "Timeout": a missing element surfaces as a failed
|
|
@@ -9,6 +17,25 @@ export const BUILT_IN_RULES = [
|
|
|
9
17
|
match: [/element\(s\) not found/i, /resolved to 0 elements/i],
|
|
10
18
|
targets: ['message', 'stack'],
|
|
11
19
|
},
|
|
20
|
+
{
|
|
21
|
+
// Before "Network", "Assertion" and "Timeout": the status is the diagnosis,
|
|
22
|
+
// whether it surfaces through `failOnStatusCode`, `toBeOK()` or a thrown
|
|
23
|
+
// error. A bare 429 is not enough (`429ms`, `Received: 429`): it needs an
|
|
24
|
+
// HTTP context.
|
|
25
|
+
name: 'Rate limited',
|
|
26
|
+
color: '#c026d3',
|
|
27
|
+
match: [/\bToo Many Requests\b/i, /\brate[- ]?limit/i, httpStatus('429')],
|
|
28
|
+
targets: ['message', 'stack'],
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'Server error',
|
|
32
|
+
color: '#7c2d12',
|
|
33
|
+
match: [
|
|
34
|
+
httpStatus('5\\d\\d'),
|
|
35
|
+
/\b5\d\d (?:Internal Server Error|Not Implemented|Bad Gateway|Service Unavailable|Gateway Time-?out|HTTP Version Not Supported)\b/i,
|
|
36
|
+
],
|
|
37
|
+
targets: ['message', 'stack'],
|
|
38
|
+
},
|
|
12
39
|
{
|
|
13
40
|
// Before "Timeout" so connection timeouts (ETIMEDOUT) count as network.
|
|
14
41
|
name: 'Network',
|
package/dist/core/signature.js
CHANGED
|
@@ -16,13 +16,17 @@ export function stripMergeTagPrefix(text) {
|
|
|
16
16
|
return text.replace(MERGE_TAG_PREFIX, '');
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
|
-
* Ordered replacements. The order matters: URLs before
|
|
20
|
-
*
|
|
21
|
-
*
|
|
19
|
+
* Ordered replacements. The order matters: URLs before e-mails (a URL may
|
|
20
|
+
* contain `user@host`) and paths (a URL contains slashes), e-mails and paths
|
|
21
|
+
* before identifiers, identifiers before durations, hex and numbers (so each
|
|
22
|
+
* is replaced as a whole), hex before numbers. See "Error signature" in
|
|
23
|
+
* docs/schema/v1.md.
|
|
22
24
|
*/
|
|
23
25
|
const REPLACEMENTS = [
|
|
24
26
|
[/\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/gi, '<uuid>'],
|
|
25
27
|
[/\b[a-z][a-z0-9+.-]*:\/\/[^\s'"`<>()[\]{}]*[^\s'"`<>()[\]{}.,;:!?]/gi, '<url>'],
|
|
28
|
+
// Local part, then a domain with at least one dot and an alphabetic TLD.
|
|
29
|
+
[/(?<![\w.%+-])[\w.%+-]+@[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)*\.[a-z]{2,}(?![\w-])/gi, '<email>'],
|
|
26
30
|
// ISO 8601 date with optional time and zone.
|
|
27
31
|
[/\b\d{4}-\d{2}-\d{2}(?:[T ]\d{2}:\d{2}(?::\d{2}(?:[.,]\d+)?)?(?:Z|[+-]\d{2}:?\d{2})?)?(?![\w:])/g, '<date>'],
|
|
28
32
|
// Time of day.
|
|
@@ -32,6 +36,13 @@ const REPLACEMENTS = [
|
|
|
32
36
|
// Absolute POSIX paths with at least two segments, and Windows drive paths.
|
|
33
37
|
[/(?<![\w.~:/\\-])\/(?:[\w.@+~-]+\/)+[\w.@+~-]+\/?/g, '<path>'],
|
|
34
38
|
[/\b[A-Za-z]:[\\/](?:[^\\/\s'"`:*?<>|]+[\\/])*[^\\/\s'"`:*?<>|]+/g, '<path>'],
|
|
39
|
+
// nanoid-like: 20+ chars of [A-Za-z0-9_-] with a lowercase letter, an
|
|
40
|
+
// uppercase letter and a digit. Mixed case keeps kebab-case and snake_case
|
|
41
|
+
// names out; a digit keeps camelCase words out.
|
|
42
|
+
[/(?<![\w-])(?=[\w-]*[a-z])(?=[\w-]*[A-Z])(?=[\w-]*\d)[\w-]{20,}(?![\w-])/g, '<id>'],
|
|
43
|
+
// cuid-like: 20+ lowercase letters and digits, with a digit and a letter
|
|
44
|
+
// beyond a-f (pure hex strings stay <hex>).
|
|
45
|
+
[/(?<![0-9A-Za-z])(?=[a-z0-9]*\d)(?=[a-z0-9]*[g-z])[a-z0-9]{20,}(?![0-9A-Za-z])/g, '<id>'],
|
|
35
46
|
[/\b\d+(?:\.\d+)?\s?(?:ms|milliseconds?|s|secs?|seconds?|m|mins?|minutes?|h|hours?)\b/gi, '<duration>'],
|
|
36
47
|
// 8+ hex chars with at least one letter (pure digit runs fall through to <n>).
|
|
37
48
|
[/(?<![0-9A-Za-z])(?=[0-9a-f]*[a-f])[0-9a-f]{8,}(?![0-9A-Za-z])/gi, '<hex>'],
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qartisan/playwright-loupe",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "Loupe —
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Loupe — an HTML reporter for Playwright: run summary, tests grouped by project and suite, dimensions from tags and annotations, and detailed failures with every attempt, error categories and signatures. Native Playwright APIs only.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"playwright",
|
|
7
7
|
"reporter",
|