@hs-web-team/eslint-config-node 5.2.0 → 5.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/cypress/rate-limit-429.js +10 -2
- package/examples/cypress-usage.md +7 -2
- package/package.json +6 -23
|
@@ -20,6 +20,10 @@ let currentOutline = null;
|
|
|
20
20
|
/** @type {string | null} */
|
|
21
21
|
let rateLimited429Outline = null;
|
|
22
22
|
|
|
23
|
+
// URLs whose path doesn't end in a media/download extension; skips media that scripts fetch (best-effort).
|
|
24
|
+
const NOT_MEDIA_OR_DOWNLOAD_URL =
|
|
25
|
+
/^(?![^?#]*\.(?:mp3|m4a|aac|wav|ogg|oga|opus|flac|mp4|m4v|mov|webm|mkv|m3u8|mpd|ts|m4s|pdf|zip)(?:[?#]|$))/i;
|
|
26
|
+
|
|
23
27
|
// cy.state('runnable') is an internal API
|
|
24
28
|
const currentRunnable = () => cy.state('runnable');
|
|
25
29
|
|
|
@@ -41,11 +45,15 @@ const disableRetriesForCurrentTest = () => {
|
|
|
41
45
|
beforeEach(() => {
|
|
42
46
|
rateLimit429Hit = null; // to ensure each scenario starts clean, in case a previous afterEach was skipped
|
|
43
47
|
|
|
44
|
-
// Observe
|
|
48
|
+
// Observe responses (middleware:true never modifies). Genuine Cloudflare 429s
|
|
45
49
|
// carry a cf-ray header; third-party 429s (Google c2dm, pixels, etc.) don't, so ignore
|
|
46
50
|
// those — otherwise we'd wrongly disable retries / skip an outline. Gate on the header,
|
|
47
51
|
// not the host, since the suite may hit several Cloudflare-fronted hosts.
|
|
48
|
-
|
|
52
|
+
//
|
|
53
|
+
// Only document/fetch/xhr: Cypress sends each matched response body to the driver over CDP,
|
|
54
|
+
// and large media bodies overflow Chrome's 100 MB buffer and hang the run. A Cloudflare 429
|
|
55
|
+
// blocks the whole IP, so page loads and API calls still see it.
|
|
56
|
+
cy.intercept({ url: NOT_MEDIA_OR_DOWNLOAD_URL, resourceType: /^(document|fetch|xhr)$/, middleware: true }, req => {
|
|
49
57
|
req.on('response', res => {
|
|
50
58
|
const ray = res.headers['cf-ray'];
|
|
51
59
|
if (res.statusCode === 429 && ray) {
|
|
@@ -131,6 +131,11 @@ IP block, so a retry can't pass — it just burns the limited request budget. Th
|
|
|
131
131
|
Detection is gated on Cloudflare's `cf-ray` response header, so unrelated third-party 429s
|
|
132
132
|
(pixels, analytics, etc.) don't trigger it.
|
|
133
133
|
|
|
134
|
+
The handler only watches `document`, `fetch` and `xhr` responses, and skips URLs ending in a
|
|
135
|
+
media or download extension (`.mp3`, `.mp4`, `.m3u8`, `.pdf`, …). Cypress sends every watched
|
|
136
|
+
response body to the driver, and large media can overflow Chrome's 100 MB DevTools buffer and
|
|
137
|
+
hang the run. A Cloudflare 429 blocks the whole IP, so page loads and API calls still catch it.
|
|
138
|
+
|
|
134
139
|
### Enabling it
|
|
135
140
|
|
|
136
141
|
Add **one file inside your `stepDefinitions` glob** (commonly
|
|
@@ -155,7 +160,7 @@ dependency your suite satisfies.
|
|
|
155
160
|
|
|
156
161
|
Real Cloudflare 429s are intermittent, so to confirm the handler fires, force one in a
|
|
157
162
|
throwaway/smoke spec with a **dynamic-reply** intercept — point it at a request the page
|
|
158
|
-
actually makes (a browser `fetch`/XHR, not `cy.request`):
|
|
163
|
+
actually makes (a page load or browser `fetch`/XHR, not `cy.request` or a static asset):
|
|
159
164
|
|
|
160
165
|
```js
|
|
161
166
|
cy.intercept('GET', '**/your-endpoint', req =>
|
|
@@ -163,7 +168,7 @@ cy.intercept('GET', '**/your-endpoint', req =>
|
|
|
163
168
|
);
|
|
164
169
|
```
|
|
165
170
|
|
|
166
|
-
The handler's
|
|
171
|
+
The handler's middleware intercept runs first and observes the response, so the test
|
|
167
172
|
fails once (no retry), carries the `[RATE-LIMIT-429]` marker, and — in a Scenario Outline —
|
|
168
173
|
the remaining examples are skipped. Use a dynamic `req.reply(...)`, not a static stub object:
|
|
169
174
|
a static stub doesn't reliably drive the response lifecycle the middleware observes.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hs-web-team/eslint-config-node",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.3.0",
|
|
4
4
|
"description": "HubSpot Marketing WebTeam shared configurations for ESLint, Prettier, Stylelint, and Cypress",
|
|
5
5
|
"files": [
|
|
6
6
|
".prettierrc.json",
|
|
@@ -110,36 +110,19 @@
|
|
|
110
110
|
"prettier": "3.9.6",
|
|
111
111
|
"prettier-plugin-gherkin": "4.0.0",
|
|
112
112
|
"strip-json-comments": "5.0.3",
|
|
113
|
+
"stylelint": "^17.1.1",
|
|
114
|
+
"stylelint-config-standard": "^40.0.0",
|
|
115
|
+
"stylelint-config-standard-scss": "^17.0.0",
|
|
116
|
+
"stylelint-declaration-strict-value": "^1.11.1",
|
|
113
117
|
"typescript-eslint": "8.68.0"
|
|
114
118
|
},
|
|
115
119
|
"peerDependencies": {
|
|
116
120
|
"@badeball/cypress-cucumber-preprocessor": "^24.0.1",
|
|
117
|
-
"cypress": "^15.21.0"
|
|
118
|
-
"stylelint": "^17.1.1",
|
|
119
|
-
"stylelint-config-standard": "^40.0.0",
|
|
120
|
-
"stylelint-config-standard-scss": "^17.0.0",
|
|
121
|
-
"stylelint-declaration-strict-value": "^1.11.1"
|
|
121
|
+
"cypress": "^15.21.0"
|
|
122
122
|
},
|
|
123
123
|
"peerDependenciesMeta": {
|
|
124
|
-
"stylelint": {
|
|
125
|
-
"optional": true
|
|
126
|
-
},
|
|
127
|
-
"stylelint-config-standard": {
|
|
128
|
-
"optional": true
|
|
129
|
-
},
|
|
130
|
-
"stylelint-config-standard-scss": {
|
|
131
|
-
"optional": true
|
|
132
|
-
},
|
|
133
|
-
"stylelint-declaration-strict-value": {
|
|
134
|
-
"optional": true
|
|
135
|
-
},
|
|
136
124
|
"cypress": {
|
|
137
125
|
"optional": true
|
|
138
126
|
}
|
|
139
|
-
},
|
|
140
|
-
"devDependencies": {
|
|
141
|
-
"stylelint": "17.15.0",
|
|
142
|
-
"stylelint-config-standard-scss": "17.0.0",
|
|
143
|
-
"stylelint-declaration-strict-value": "1.12.1"
|
|
144
127
|
}
|
|
145
128
|
}
|