Skip to content

Commit 5870e99

Browse files
AgnesTouletoleiadeankur22mstoykovjoanlopez
authored
Release notes v1.3.0 (#5169)
* docs: add v1.3.0 release notes * Add #5051 to 1.3.0 release notes * Add backported fixes * k6packaged changes * Add changes to release v1.3.0 * Add locator.locator in release notes * add deprecations notice * Adds missing merged PRs from milestone into release notes * Add 5163 to release notes * Add notes for page.waitForResponse * Add `locator.boundingBox` in release notes * Add FID deprecation in roadmap * Add link to issue for the deprecation of FID * Add frameLocator details to release notes * Add getBy release notes changes * Add extended explanations for the summary deprecations * Add small missing PRs * Add locator.filter and options * Organize by feature * Organize by locator filtering feature * Remove PR 5131 as it's a review PR * Unsplash summary items * Add thanks for page.waitForResponse * Add missing #5178 * Update release notes/v1.3.0.md Co-authored-by: Ivan <[email protected]> * Acknoweldge external contribution * Add OpenTelemtry roadmap * Remove placeholder * Add clearTimeout bug fix Co-authored-by: Mihail Stoykov <[email protected]> * Add links to documentation * Remove locator filtering future plans Co-authored-by: Ankur <[email protected]> * Fix typo Co-authored-by: Ankur <[email protected]> * Update web.dev link Co-authored-by: Ankur <[email protected]> --------- Co-authored-by: oleiade <[email protected]> Co-authored-by: ankur22 <[email protected]> Co-authored-by: Mihail Stoykov <[email protected]> Co-authored-by: Joan López de la Franca Beltran <[email protected]> Co-authored-by: İnanç Gümüş <[email protected]> Co-authored-by: Théo Crevon <[email protected]> Co-authored-by: Ivan <[email protected]> Co-authored-by: Mihail Stoykov <[email protected]>
1 parent c7fdf34 commit 5870e99

File tree

1 file changed

+276
-0
lines changed

1 file changed

+276
-0
lines changed

release notes/v1.3.0.md

Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
k6 v1.3.0 is here 🎉! This release includes:
2+
3+
- Browser module gets:
4+
- `locator.locator`, `locator.contentFrame`, and `FrameLocator.locator` for powerful locator chaining and iframe handling.
5+
- `locator|frame|FrameLocator.getBy*` for targeting elements without relying on brittle CSS selectors.
6+
- `locator.filter` for filtering locators for more precise element targeting.
7+
- `locator.boundingBox` for retrieving element geometry.
8+
- `page.waitForResponse` for waiting on specific HTTP responses.
9+
10+
## Deprecations
11+
12+
### A new summary mode `disabled` has been introduced to replace the "no summary" option [#5118](https://github.com/grafana/k6/pull/5118)
13+
14+
The `--no-summary` flag and its corresponding environment variable `K6_NO_SUMMARY` have been deprecated in favor of
15+
the new `disabled` summary mode. This change unifies the configuration experience for controlling the end-of-test summary.
16+
17+
You can now disable the end-of-test summary with either `--summary-mode=disabled` or `K6_SUMMARY_MODE=disabled`.
18+
19+
### The `legacy` summary mode has been deprecated [#5138](https://github.com/grafana/k6/pull/5138)
20+
21+
The `legacy` summary mode was introduced in k6 v1.0, when the end-of-test summary was revamped with the addition of two
22+
new modes: `compact` and `full`.
23+
24+
Its purpose was to ease the transition for users who relied heavily on the old summary format.
25+
However, we’ve now reached the point where it’s time to deprecate it.
26+
27+
The plan is to fully remove it in k6 v2.0, so please migrate to either `compact` or `full` to ensure readiness for the
28+
next major release.
29+
30+
## New features
31+
32+
### `locator.locator` [#5073](https://github.com/grafana/k6/pull/5073)
33+
34+
The [`locator.locator`](https://grafana.com/docs/k6/latest/javascript-api/k6-browser/locator/locator/) method allows you to define locators relative to a parent locator, enabling powerful locator chaining and nesting. This feature lets you create more precise element targeting by combining multiple selectors in a hierarchical manner.
35+
36+
```javascript
37+
await page
38+
.locator('[data-testid="inventory"]')
39+
.locator('[data-item="apples"]')
40+
.locator('button.add')
41+
.click();
42+
```
43+
44+
This nesting capability provides a more intuitive way to navigate complex DOM structures and serves as the foundation for other `locator` APIs in this release that require such hierarchical targeting.
45+
46+
### `locator.contentFrame` [#5075](https://github.com/grafana/k6/pull/5075)
47+
48+
The browser module now supports [`locator.contentFrame()`](https://grafana.com/docs/k6/latest/javascript-api/k6-browser/locator/contentframe/), which returns a new type [`frameLocator`](https://grafana.com/docs/k6/latest/javascript-api/k6-browser/framelocator/). This method is essential for switching context from the parent page to iframe contents.
49+
50+
`frameLocator` types target iframe elements on the page and provide a gateway to interact with their contents. Unlike regular `locator`s that work within the current `frame` context, `frameLocator`s specifically target iframe elements and prepare them for content interaction.
51+
52+
This approach is essential for iframe interaction because:
53+
- Iframes create separate DOM contexts that require special handling.
54+
- Browsers enforce security boundaries between frames.
55+
- Iframe content may load asynchronously and needs proper waiting.
56+
- Using `elementHandle` for iframe interactions is error-prone and can lead to stale references, while `frameLocator` provide reliable, auto-retrying approaches.
57+
58+
Example usage:
59+
```javascript
60+
// Get iframe element and switch to its content frame
61+
const iframeLocator = page.locator('iframe[name="payment-form"]');
62+
const frame = await iframeLocator.contentFrame();
63+
```
64+
65+
### `frameLocator.locator` [#5075](https://github.com/grafana/k6/pull/5075)
66+
67+
We've also added [`frameLocator.locator`](https://grafana.com/docs/k6/latest/javascript-api/k6-browser/framelocator/locator/) which allows you to create `locator`s for elements inside an iframe. Once you've targeted an iframe with `page.contentFrame()`, you can use `.locator()` to find and interact with elements within that iframe's content with the `frameLocator` type.
68+
69+
Example usage:
70+
```javascript
71+
// Target an iframe and interact with elements inside it
72+
const iframe = page.locator('iframe[name="checkout-frame"]').contentFrame();
73+
await iframe.locator('input[name="card-number"]').fill('4111111111111111');
74+
await iframe.locator('button[type="submit"]').click();
75+
```
76+
77+
This functionality enables testing of complex web applications that use iframes for embedded content, payment processing, authentication widgets, and third-party integrations.
78+
79+
### `locator.boundingBox` [#5076](https://github.com/grafana/k6/pull/5076)
80+
81+
The browser module now supports [`locator.boundingBox()`](https://grafana.com/docs/k6/latest/javascript-api/k6-browser/locator/boundingbox/), which returns the bounding box of an element as a rectangle with position and size information. This method provides essential geometric data about elements on the page, making it valuable for visual testing, and layout verification.
82+
83+
Using `locator.boundingBox()` is recommended over `elementHandle.boundingBox()` because locators have built-in auto-waiting and retry logic, making them more resilient to dynamic content and DOM changes. While element handles can become stale if the page updates, locators represent a live query that gets re-evaluated, ensuring more reliable test execution.
84+
85+
The method returns a rectangle object with `x`, `y`, `width`, and `height` properties, or `null` if the element is not visible:
86+
87+
```javascript
88+
// Get bounding box of an element
89+
const submitButton = page.locator('button[type="submit"]');
90+
const rect = await submitButton.boundingBox();
91+
```
92+
93+
### Locator filtering [#5114](https://github.com/grafana/k6/pull/5114), [#5150](https://github.com/grafana/k6/pull/5150)
94+
95+
The browser module now supports filtering options for locators, allowing you to create more precise and reliable element selections. This enhancement improves the robustness of your tests by enabling you to target elements that contain or exclude specific text, reducing reliance on brittle CSS selectors.
96+
97+
[**`locator.filter()`**](https://grafana.com/docs/k6/latest/javascript-api/k6-browser/locator/filter/) creates a new `locator` that matches only elements containing or excluding specified text.
98+
99+
```javascript
100+
// Filter list items that contain specific text
101+
const product2Item = page
102+
.locator('li')
103+
.filter({ hasText: 'Product 2' });
104+
105+
// Filter items that do NOT contain specific text using regex
106+
const otherProducts = page
107+
.locator('li')
108+
.filter({ hasNotText: /Product 2/ });
109+
```
110+
111+
It's also possible to filter locators during their creation with options.
112+
113+
**`page.locator(selector, options)`** creates page locators with optional text filtering:
114+
115+
```javascript
116+
// Create locators with text filtering during creation
117+
const submitButton = page.locator('button', { hasText: 'Submit Order' });
118+
await submitButton.click();
119+
```
120+
121+
**`frame.locator(selector, options)`** creates frame locators with optional text filtering:
122+
123+
```javascript
124+
// Filter elements within frame context
125+
const frame = page.mainFrame();
126+
const input = frame.locator('input', { hasNotText: 'Disabled' });
127+
```
128+
129+
**`locator.locator(selector, options)`** chains locators with optional text filtering:
130+
131+
```javascript
132+
// Chain locators with filtering options
133+
await page
134+
.locator('[data-testid="inventory"]')
135+
.locator('[data-item="apples"]', { hasText: 'Green' })
136+
.click();
137+
```
138+
139+
**`frameLocator.locator(selector, options)`** create locators within iframe content with optional text filtering:
140+
141+
```javascript
142+
// Filter elements within iframe content
143+
const iframe = page.locator('iframe').contentFrame();
144+
await iframe.locator('button', { hasText: 'Submit Payment' }).click();
145+
```
146+
147+
### `frame.getBy*`, `locator.getBy*`, `frameLocator.getBy*` [#5105](https://github.com/grafana/k6/pull/5105), [#5106](https://github.com/grafana/k6/pull/5106), [#5135](https://github.com/grafana/k6/pull/5135)
148+
149+
The browser module now supports all `getBy*` methods on `frame`, `locator`, and `frameLocator` types, expanding on the `page.getBy*` APIs introduced in v1.2.1. This enhancement provides consistent element targeting across all browser automation contexts, improving Playwright compatibility and offering more flexible testing workflows. The available methods on all types are:
150+
151+
- `getByRole()` - Find elements by ARIA role
152+
- `getByText()` - Find elements by text content
153+
- `getByLabel()` - Find elements by associated label text
154+
- `getByPlaceholder()` - Find elements by placeholder text
155+
- `getByAltText()` - Find elements by alt text
156+
- `getByTitle()` - Find elements by title attribute
157+
- `getByTestId()` - Find elements by data-testid attribute
158+
159+
#### Examples across different types
160+
161+
```javascript
162+
// Frame context
163+
const frame = page.mainFrame();
164+
await frame.getByRole('button', { name: 'Submit' }).click();
165+
await frame.getByLabel('Email').fill('[email protected]');
166+
167+
// Locator context (for scoped searches)
168+
const form = page.locator('form.checkout');
169+
await form.getByRole('textbox', { name: 'Card number' }).fill('4111111111111111');
170+
await form.getByTestId('submit-button').click();
171+
172+
// FrameLocator context (for iframe content)
173+
const paymentFrame = page.locator('iframe').contentFrame();
174+
await paymentFrame.getByLabel('Cardholder name').fill('John Doe');
175+
await paymentFrame.getByRole('button', { name: 'Pay now' }).click();
176+
177+
// Chaining for precise targeting
178+
await page
179+
.locator('.product-list')
180+
.getByText('Premium Plan')
181+
.getByRole('button', { name: 'Select' })
182+
.click();
183+
```
184+
185+
This expansion makes k6 browser automation more versatile and aligns with modern testing practices where element targeting by semantic attributes (roles, labels, text) is preferred over fragile CSS and XPath selectors.
186+
187+
### `page.waitForResponse` [#5002](https://github.com/grafana/k6/pull/5002)
188+
189+
The browser module now supports [`page.waitForResponse()`](https://grafana.com/docs/k6/latest/javascript-api/k6-browser/page/waitforresponse/), which allows you to wait for HTTP responses that match specific URL patterns during browser automation. This method is particularly valuable for testing scenarios where you need to ensure specific network requests complete before proceeding with test actions.
190+
191+
The method supports multiple URL pattern matching strategies:
192+
193+
```javascript
194+
// Wait for exact URL match
195+
await page.waitForResponse('https://api.example.com/data');
196+
197+
// Wait for regex pattern match
198+
await page.waitForResponse(/\/api\/.*\.json$/);
199+
200+
// Use with Promise.all for coordinated actions
201+
await Promise.all([
202+
page.waitForResponse('https://api.example.com/user-data'),
203+
page.click('button[data-testid="load-user-data"]')
204+
]);
205+
```
206+
207+
This complements the existing `waitForURL` method by focusing on HTTP responses rather than navigation events, providing more granular control over network-dependent test scenarios.
208+
209+
Thank you, @HasithDeAlwis, for contributing this feature.
210+
211+
## UX improvements and enhancements
212+
213+
- [#5164](https://github.com/grafana/k6/pull/5164) Rate metrics are now exported as a single counter with a label that can have two values: zero and nonzero.
214+
- [#5117](https://github.com/grafana/k6/pull/5117) Unifies unauthenticated errors for Cloud commands.
215+
- [#5125](https://github.com/grafana/k6/pull/5125) Changes a warn log to a debug when a worker type is used on a website under test.
216+
- [#5111](https://github.com/grafana/k6/pull/5111) Adds retries to actionability based APIs (`locator`) when elements aren't visible.
217+
- [#5004](https://github.com/grafana/k6/pull/5004) Removes undefined headers from `route.continue`/`fulfill`.
218+
- [#4984](https://github.com/grafana/k6/pull/4984) Adds link to documentation in `k6 --help` output. Thank you, @Nishant891 for the change.
219+
220+
## Bug fixes
221+
222+
- [#5079](https://github.com/grafana/k6/pull/5079) Fixes version of k6 when it is built with xk6.
223+
- [#5057](https://github.com/grafana/k6/pull/5057) Fixes a panic on the deprecated `k6 login cloud` command. Thanks @indygriffiths for reporting it!
224+
- [#5059](https://github.com/grafana/k6/pull/5059) Fixes group order in end of test summary when scenarios are used.
225+
- [#5081](https://github.com/grafana/k6/pull/5081) Fixes auto extension resolution only working if binary is called `k6` after a fix in v1.2.2.
226+
- [#5089](https://github.com/grafana/k6/pull/5089) Fixes gRPC calls not using loaded types and erroring out, especially around the usage of `Any`.
227+
- [#5071](https://github.com/grafana/k6/pull/5071), [#5086](https://github.com/grafana/k6/pull/5086), [#5163](https://github.com/grafana/k6/pull/5163) Fixes `click` action in browser module when working in `iframe`s and CORS.
228+
- [#5084](https://github.com/grafana/k6/pull/5084) Fixes a browser module issue when adopting elements from `util` to `main` execution contexts in Chromium.
229+
- [#5178](https://github.com/grafana/k6/pull/5178) Fixes a subtle metric labelling issue in Prometheus RW output.
230+
- [#5200](https://github.com/grafana/k6/pull/5200) Fixes a bug where clearTimeout would not recalculate the timer but instead will run the next timer earlier if it used to remove the earliest one. Thanks to @kyriog :bow:.
231+
232+
## Maintenance and internal improvements
233+
234+
- [#5165](https://github.com/grafana/k6/pull/5165) Fixes arguments order for multiple `{require|assert}.{Equal|NotEqual}` and equivalent calls.
235+
- [#5157](https://github.com/grafana/k6/pull/5157) Fixes the test `TestURLSkipRequest` for Chrome 140+.
236+
- [#5074](https://github.com/grafana/k6/pull/5074), [#5078](https://github.com/grafana/k6/pull/5078) Uses common.IsNullish through the code instead of other variants of it or custom helpers.
237+
- [#5072](https://github.com/grafana/k6/pull/5072), [#5107](https://github.com/grafana/k6/pull/5107), [#5108](https://github.com/grafana/k6/pull/5108) Update k6packager debian to latest LTS and fixes due to the update.
238+
- [#5051](https://github.com/grafana/k6/pull/5051), [#5052](https://github.com/grafana/k6/pull/5052), [#5053](https://github.com/grafana/k6/pull/5053) Adds tests and refactors `getBy*` and `waitForURL` implementations.
239+
- [#5101](https://github.com/grafana/k6/pull/5101) Updates times to nanoseconds to make tests less flakey in CI.
240+
- [#5122](https://github.com/grafana/k6/pull/5122) Migrates to use a new code signing process for Windows binaries instead of using the static code-signing certificate. Thanks @martincostello for the contribution!
241+
- [#5048](https://github.com/grafana/k6/pull/5048) Updates release issue template after v1.2.0
242+
- [#5046](https://github.com/grafana/k6/pull/5046) Adds architecture overview and code authoring instructions for Claude Code and alike.
243+
244+
## Roadmap
245+
246+
### Deprecation of First Input Delay (FID) Web Vital
247+
248+
Following the official [web vitals guidance](https://web.dev/blog/fid), First Input Delay (FID) is no longer a Core Web Vital as of September 9, 2024, having been replaced by Interaction to Next Paint (INP). The k6 browser module already emits INP metrics, and we're planning to deprecate FID support to align with industry standards.
249+
250+
FID only measures the delay before the browser runs your event handler, so it ignores the time your code takes and the delay to paint the UI—often underestimating how slow an interaction feels. INP captures the full interaction latency (input delay + processing + next paint) across a page’s interactions, so it better reflects real user-perceived responsiveness and is replacing FID.
251+
252+
#### Planned timeline
253+
254+
- v1.4.x+: Deprecation warnings will appear in the terminal when FID metrics are used [#5179](https://github.com/grafana/k6/issues/5179).
255+
- Grafana Cloud k6: Similar deprecation warnings will be shown in the cloud platform.
256+
- v2.0: Complete removal of FID metric support.
257+
258+
#### Action required
259+
260+
If you're currently using FID in your test scripts for thresholds or relying on it in external integrations, you should migrate to using INP as soon as possible.
261+
262+
```javascript
263+
// Instead of relying on FID
264+
export const options = {
265+
thresholds: {
266+
// 'browser_web_vital_fid': ['p(95)<100'], // Deprecated
267+
'browser_web_vital_inp': ['p(95)<200'], // Use INP instead
268+
},
269+
};
270+
```
271+
272+
This change ensures k6 browser testing stays aligned with modern web performance best practices and Core Web Vitals standards.
273+
274+
### OpenTelemetry stabilization
275+
276+
We aim to stabilize OpenTelemetry's experimental metric output, promoting vendor neutrality for metric outputs. OpenTelemetry is becoming the standard protocol for metric format in observability. Our goal is to enable k6 users to utilize their preferred metric backend storage without any technological imposition.

0 commit comments

Comments
 (0)