k6 `v1.1.0` is here 🎉! This release includes:

- New `count`, `nth`, `first`, and `last` methods for the browser module's Locator API [#4797](https://github.com/grafana/k6/pull/4797), [#4825](https://github.com/grafana/k6/pull/4825)
- The `k6/experimental/webcrypto` module has been removed as its functionality is available globally.
- Group results in the `full` end-of-test summary are now sorted as in code and properly indented.

## Breaking changes

*As per our [stability guarantees](https://grafana.com/docs/k6/latest/reference/versioning-and-stability-guarantees/),
breaking changes across minor releases are allowed only for experimental features.*

### Breaking changes for experimental modules

#### Remove experimental `k6/experimental/webcrypto` module [#4851](https://github.com/grafana/k6/pull/4851)

The [WebCrypto API](https://grafana.com/docs/k6/latest/javascript-api/crypto/) has been available globally since `v1.0.0-rc1` (or `v0.58.0`), and now the experimental import (`k6/experimental/webcrypto`) is no longer available.

The required change for users is to remove the `import`; the rest of the code should work.

## New features

### New `count` method for the browser module's Locator API [#4797](https://github.com/grafana/k6/pull/4797)

The new `locator.Count` method returns the number of elements matching the `locator`. Unlike other Locator API methods, `locator.Count` returns the result immediately and doesn't wait for the elements to be visible.

```javascript
import { expect } from "https://jslib.k6.io/k6-testing/0.4.0/index.js";
import { browser } from 'k6/browser'

export const options = {
  scenarios: {
    ui: {
      executor: 'shared-iterations',
      options: {
        browser: {
          type: 'chromium',
        },
      },
    },
  },
}

export default async function () {
  const page = await browser.newPage()
  await page.goto('https://quickpizza.grafana.com/login')

  expect(await page.locator('input').count()).toEqual(3);

  await page.close();
}
```

### New `nth`, `first` and `last` methods for the browser module's Locator API [#4825](https://github.com/grafana/k6/pull/4825)

The new Locator API methods, `nth`, `first`, and `last`, can select a single element from multiple elements matched by a `locator`. For example, selecting a single item from a catalogue of items on an e-commerce website. Because items in this catalogue generally change often and selecting an exact element may fail in future test runs, the new methods help to prevent flaky tests, leading to more reliable tests.

```javascript
import { expect } from "https://jslib.k6.io/k6-testing/0.4.0/index.js";
import { browser } from 'k6/browser'

export const options = {
  scenarios: {
    ui: {
      executor: 'shared-iterations',
      options: {
        browser: {
          type: 'chromium',
        },
      },
    },
  },
}

export default async function () {
  const page = await browser.newPage()
  await page.goto('https://quickpizza.grafana.com')

  await expect(await page.locator('p').first()).toContainText('QuickPizza');
  await expect(await page.locator('p').nth(4)).toContainText('QuickPizza Labs.');
  await expect(await page.locator('p').last()).toContainText('Contribute to QuickPizza');

  await page.close();
}
```

## UX improvements and enhancements

- [#4807](https://github.com/grafana/k6/pull/4807) Sorts `full` end-of-test summary group results as in code and fixes the indentation. Thanks, @the-it, for the contribution! 
- [#4832](https://github.com/grafana/k6/pull/4832) Uses consistent error messages in the execution config options.

## Bug fixes

- [#4794](https://github.com/grafana/k6/pull/4794) Fixes race conditions from stringifying types in `k6/browser`.
- [#4809](https://github.com/grafana/k6/pull/4809) Fixes the `locator.fill` method when used on react based websites.
- [#4831](https://github.com/grafana/k6/pull/4831) Fixes the Dockerfile for k8s use by setting the user to `12345` instead of `k6` to avoid having to work with `runAsUser` in the pod manifest file.
- [#4845](https://github.com/grafana/k6/pull/4845) Fixes an infrequent panic when `click` is called.

## Maintenance and internal improvements

- [#4608](https://github.com/grafana/k6/pull/4608) Enables the 'copyloopvar' linter.
- [#4744](https://github.com/grafana/k6/pull/4744) Updates the 'golangci-lint' linter to v2.
- [#4746](https://github.com/grafana/k6/pull/4746) Adds a collection of small `k6/browser` performance improvements.
- [#4750](https://github.com/grafana/k6/pull/4750) Fixes the lint GHA.
- [#4775](https://github.com/grafana/k6/pull/4775) Updates the version of the golangci-lint GHA.
- [#4784](https://github.com/grafana/k6/pull/4784) Fixes the golangci-lint version detection and execution. Thanks, @tbourrely, for the contribution!
- [#4785](https://github.com/grafana/k6/pull/4785) Updates the `chromedp/cdproto` dependency and adjusts the Browser module accordingly.
- [#4800](https://github.com/grafana/k6/pull/4800) Allows un/marshaling of invalid UTF-8 when using JSONv2 within the Browser module. 
- [#4802](https://github.com/grafana/k6/pull/4802) Fixes the `examples/grpc_server` and updates its dependencies. 
- [#4822](https://github.com/grafana/k6/pull/4822) Uses the `CODECOV_TOKEN` variable for GH Workflows from Vault.
- [#4831](https://github.com/grafana/k6/pull/4831) Fixes the default user defined in the Dockerfile.
- [#4833](https://github.com/grafana/k6/pull/4833) Retrieves secrets from Vault and adjusts the 'k6packager' deployment process.
- [#4837](https://github.com/grafana/k6/pull/4837), [#4847](https://github.com/grafana/k6/pull/4847) Prevent Codecov from running on forks.
- [#4848](https://github.com/grafana/k6/pull/4848) Enables CI pipelines to be executed also on ARM (`ubuntu-24.04-arm`). Thanks, @nadiamoe, for the contribution!
- [#4855](https://github.com/grafana/k6/pull/4855) Adds some changes to make Browser tests more stable.
- [#4780](https://github.com/grafana/k6/pull/4780), [#4781](https://github.com/grafana/k6/pull/4781), [#4782](https://github.com/grafana/k6/pull/4782), [#4786](https://github.com/grafana/k6/pull/4786), [#4798](https://github.com/grafana/k6/pull/4798), [#4816](https://github.com/grafana/k6/pull/4816), [#4821](https://github.com/grafana/k6/pull/4821), [#4835](https://github.com/grafana/k6/pull/4835), [#4840](https://github.com/grafana/k6/pull/4840) Update direct dependencies.
- [#4864](https://github.com/grafana/k6/pull/4864) Updates the logging to debug and adds more context to it when waiting for an element to be detached.

## Roadmap

### Official Testing/Assertions Module
We're working to integrate a built-in testing and assertions module that's compatible with Playwright's in k6. You can try the current implementation using the [k6 testing jslib](https://github.com/grafana/k6-jslib-testing), which serves as our work-in-progress implementation for what will become the official `k6/test` module (final name TBD). We'd love your feedback on issue [#4805](https://github.com/grafana/k6/issues/4805).

### Enhanced Machine-Readable Test Results

We're developing the next version of k6's end-of-test summary to make it easier to integrate test results into CI/CD pipelines and automated workflows. This new format will be officially supported, versioned, and designed specifically for programmatic use. Follow our progress, and provide us with feedback on issue [#4803](https://github.com/grafana/k6/issues/4803).