@qaguardian/playwright-score 0.2.0 → 0.3.0

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/METHODOLOGY.md CHANGED
@@ -161,4 +161,14 @@ See package rule docs / source `profiles.ts`. High level:
161
161
  - **playwrightHygiene:** waits, force, networkidle, missing await, handles, conditionals
162
162
  - **assertions:** expect-expect, empty tests, web-first preference
163
163
  - **locators:** ratio metric only (for score); raw-locator ESLint in findings
164
- - **structure:** focused/skipped, oversized file, describe shape
164
+ - **structure:** focused/skipped, oversized file, describe shape
165
+
166
+ ### Active rule set (frozen)
167
+
168
+ The exact ESLint rules that produce sqs-v1 findings are enabled explicitly
169
+ in `eslint-runner.ts` with fixed severities — the score never inherits
170
+ eslint-plugin-playwright's `recommended` set at install time, so identical
171
+ code scores identically regardless of which plugin version npm resolves.
172
+ (Versions ≤0.2.0 intended to inherit `recommended` but a config-shape bug
173
+ dropped it entirely; 0.3.0 froze the intended set explicitly. See
174
+ CHANGELOG.)
package/README.md CHANGED
@@ -16,7 +16,44 @@ Page Object Model import resolution, ...).
16
16
 
17
17
  The score never calls an LLM. AI may *generate* or *repair* code using findings; **rules grade code**.
18
18
 
19
- See [METHODOLOGY.md](./METHODOLOGY.md) for the frozen formula, [VALIDATION.md](./VALIDATION.md) for real-world results against public repos (cal.com, Grafana, Mattermost, ...) and a re-runnable script to reproduce them, or the full product write-up on the [landing page](https://qaguardian.com/open-source/playwright-score).
19
+ ## Real-world results
20
+
21
+ 17 public Playwright suites, scored with the published package against each
22
+ project's actual source — chosen to include both well-known,
23
+ heavily-engineered platforms and smaller, less mature projects. Not curated
24
+ to look good: 3 of 17 fail the default threshold, for real, verifiable
25
+ reasons (see [VALIDATION.md](./VALIDATION.md)).
26
+
27
+ **17 suites · 1,228 files · 6,037 tests · 14/17 passed (80% threshold)**
28
+
29
+ | Repo (source scanned) | Score | Grade | Result |
30
+ |---|---:|:-:|:-:|
31
+ | [Playwright (own TodoMVC example)](https://github.com/microsoft/playwright/tree/main/examples/todomvc) | 98/100 | A | PASS |
32
+ | [Supabase](https://github.com/supabase/supabase/tree/master/e2e) | 97/100 | A | PASS |
33
+ | [Documenso](https://github.com/documenso/documenso/tree/main/packages/app-tests) | 96/100 | A | PASS |
34
+ | [Storybook](https://github.com/storybookjs/storybook/tree/next/code/e2e-internal) | 96/100 | A | PASS |
35
+ | [freeCodeCamp](https://github.com/freeCodeCamp/freeCodeCamp/tree/main/e2e) | 96/100 | A | PASS |
36
+ | [n8n](https://github.com/n8n-io/n8n/tree/master/packages/testing/playwright) | 95/100 | A | PASS |
37
+ | [dub](https://github.com/dubinc/dub/tree/main/apps/web/playwright) | 95/100 | A | PASS |
38
+ | [novu](https://github.com/novuhq/novu/tree/next/apps/dashboard/tests) | 93/100 | A | PASS |
39
+ | [Grafana](https://github.com/grafana/grafana/tree/main/e2e-playwright) | 91/100 | A | PASS |
40
+ | [PostHog](https://github.com/PostHog/posthog/tree/master/playwright) | 90/100 | A | PASS |
41
+ | [sencho](https://github.com/Studio-Saelix/sencho/tree/main/e2e) | 90/100 | A | PASS |
42
+ | [Mattermost](https://github.com/mattermost/mattermost/tree/master/e2e-tests/playwright) | 89/100 | B | PASS |
43
+ | [Immich](https://github.com/immich-app/immich/tree/main/e2e/src/specs) | 89/100 | B | PASS |
44
+ | [cal.com](https://github.com/calcom/cal.com/tree/main/apps/web/playwright) | 84/100 | B | PASS |
45
+ | [livecodes](https://github.com/live-codes/livecodes/tree/develop/e2e) | 78/100 | C | FAIL |
46
+ | [openplayerjs](https://github.com/openplayerjs/openplayerjs/tree/master/e2e) | 77/100 | C | FAIL |
47
+ | [TheCyberHub](https://github.com/th3cyb3rhub/TheCyberHub/tree/dev/e2e) | 68/100 | D | FAIL |
48
+
49
+ Repo names link to the exact source scanned. Full methodology, findings
50
+ breakdown, and `scripts/validate-corpus.sh` to reproduce every number here
51
+ yourself live in [VALIDATION.md](./VALIDATION.md). A self-contained visual
52
+ report of an earlier five-suite audit lives at
53
+ [`docs/scorecard.html`](./docs/scorecard.html) — host it wherever
54
+ (GitHub Pages, qaguardian.com, ...).
55
+
56
+ See [METHODOLOGY.md](./METHODOLOGY.md) for the frozen formula, or the full product write-up on the [landing page](https://qaguardian.com/open-source/playwright-score).
20
57
 
21
58
  ## Install
22
59
 
@@ -5,8 +5,6 @@ import playwright from 'eslint-plugin-playwright';
5
5
  import { basePlugin } from './rules/base-plugin.js';
6
6
  import { mapRule } from './profiles.js';
7
7
  function buildConfig(assertFunctionNames) {
8
- const playwrightRecommended = playwright.configs?.['flat/recommended'] ??
9
- playwright.configs?.recommended;
10
8
  const base = [
11
9
  {
12
10
  files: ['**/*.{ts,tsx,js,jsx,mjs,cjs}'],
@@ -89,14 +87,34 @@ function buildConfig(assertFunctionNames) {
89
87
  'playwright/prefer-native-locators': 'warn',
90
88
  // Matches eslint-plugin-playwright's own recommended severity.
91
89
  'playwright/prefer-web-first-assertions': 'error',
90
+ // The rules below complete the sqs-v1 rule set from
91
+ // profiles.ts's ESLINT_RULE_MAP. Earlier versions (<=0.2.0)
92
+ // expected them to arrive via eslint-plugin-playwright's
93
+ // flat/recommended config, but the spread only handled an array
94
+ // shape while the plugin exports a single config object — so the
95
+ // entire recommended set was silently dropped and these rules
96
+ // never ran (METHODOLOGY.md's hygiene dimension lists
97
+ // "conditionals" and "handles", yet neither could ever fire).
98
+ // They are enabled explicitly and frozen here on purpose:
99
+ // eslint-plugin-playwright is a ^range dependency, and inheriting
100
+ // whatever its recommended set says at install time would make
101
+ // identical code score differently across installs. Severities
102
+ // mirror upstream flat/recommended as of eslint-plugin-playwright
103
+ // 2.x. require-top-level-describe stays disabled deliberately —
104
+ // it is stylistic, not in upstream recommended, and would
105
+ // penalize idiomatic describe-less suites.
106
+ 'playwright/no-conditional-in-test': 'warn',
107
+ 'playwright/no-conditional-expect': 'warn',
108
+ 'playwright/no-element-handle': 'warn',
109
+ 'playwright/no-eval': 'warn',
110
+ 'playwright/no-page-pause': 'warn',
111
+ 'playwright/no-useless-await': 'warn',
112
+ 'playwright/valid-expect': 'error',
113
+ 'playwright/no-standalone-expect': 'error',
114
+ 'playwright/max-nested-describe': 'warn',
92
115
  },
93
116
  },
94
117
  ];
95
- // Prefer spreading official recommended flat config when available
96
- if (Array.isArray(playwrightRecommended)) {
97
- const configs = playwrightRecommended;
98
- return [...configs, base[0]];
99
- }
100
118
  return base;
101
119
  }
102
120
  function toSeverity(eslintSeverity, override) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qaguardian/playwright-score",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Deterministic, AI-free Playwright spec quality score (sqs-v1).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",