Skip to content

Comments

fix(deps): update module go.k6.io/k6 to v1.6.1#12

Open
renovate-sh-app[bot] wants to merge 1 commit intomainfrom
renovate/go.k6.io-k6-1.x
Open

fix(deps): update module go.k6.io/k6 to v1.6.1#12
renovate-sh-app[bot] wants to merge 1 commit intomainfrom
renovate/go.k6.io-k6-1.x

Conversation

@renovate-sh-app
Copy link
Contributor

@renovate-sh-app renovate-sh-app bot commented Nov 10, 2025

ℹ️ Note

This PR body was truncated due to platform limits.

This PR contains the following updates:

Package Change Age Confidence
go.k6.io/k6 v1.2.3v1.6.1 age confidence

Release Notes

grafana/k6 (go.k6.io/k6)

v1.6.1

Compare Source

k6 v1.6.1 is here! This patch release includes:

  • Bug fix for a race condition in the experimental CSV module
  • Bug fix for manifest k6 version override
  • Version updates for Go toolchain and Docker images

Bug fixes

  • #​5632 Fixes a race condition in the experimental/csv module when multiple files with async code use csv.parse in parallel during initialization.
  • #​5642 Fixes an issue where k6 was not always added as a build dependency, preventing manifests from overriding the k6 version.

Maintenance and security updates

  • #​5641 Adds chromium as an explicit dependency for with-browser Docker image.
  • #​5646 Updates Go toolchain version to 1.24.13.
  • #​5654 Updates the used Go version in the Docker image to v1.25.7.

v1.6.0

Compare Source

k6 v1.6.0 is here 🎉! This release includes:

  • Cloud commands now support configurable default Grafana Cloud stack.
  • New k6 deps command for analyzing script dependencies.
  • Browser APIs enhancements with frameLocator(), goBack(), goForward() methods.
  • Crypto module adds PBKDF2 support for password-based key derivation.
  • jslib gets a new TOTP library for time-based one-time password generation and validation.
  • New mcp-k6 MCP server for AI-assisted k6 script writing.
Breaking changes

There are no breaking changes in this release.

New features
Configurable default stack for Cloud commands #​5420

Cloud commands now support configuring the default Grafana Cloud stack you want to use. The stack slug (or stack id) is used by the Cloud to determine which default project to use when not explicitly provided.

Previously, users had to specify the project id for every test run. With this change, you can configure a default stack during login, and k6 will use it to automatically resolve the appropriate default project. This is particularly useful for organizations with multiple Grafana Cloud stacks or when working across different teams and environments.

Users can also set up a specific stack for every test run, either using the new option stackID or the environment variable K6_CLOUD_STACK_ID.

Please note that, in k6 v2, this stack information will become mandatory to run a test.

# Login interactively and select default stack
k6 cloud login

# Login and set default stack with token
k6 cloud login --token $MY_TOKEN --stack my-stack-slug

# Run test using the configured default stack
k6 cloud run script.js

# Run test using a specific stack
K6_CLOUD_STACK_ID=12345 k6 cloud run script.js

# Stack id can also be set in the options
export const options = {
  cloud: {
    stackID: 123,
    projectID: 789,  // If the project does not belong to the stack, this will throw an error
  },
};

This simplifies the cloud testing workflow and prepares k6 for upcoming changes to the Grafana Cloud k6 authentication process, where the stack will eventually become mandatory.

k6 deps command and manifest support #​5410, #​5427

A new k6 deps command is now available to analyze and list all dependencies of a given script or archive. This is particularly useful for understanding which extensions are required to run a script, especially when using auto extension resolution.

The command identifies all imports in your script and lists dependencies that might be needed for building a new binary with auto extension resolution. Like auto extension resolution itself, this only accounts for imports, not dynamic require() calls.

# Analyze script dependencies
k6 deps script.js

# Output in JSON format for programmatic consumption
k6 deps --json script.js

# Analyze archived test dependencies
k6 deps archive.tar

This makes it easier to understand extension requirements, share scripts with clear dependency information, and integrate k6 into automated build pipelines.

In addition, k6 now supports a manifest that specifies default version constraints for dependencies when no version is defined in the script using pragmas. If a dependency is imported without an explicit version, it defaults to "*", and the manifest can be used to replace that with a concrete version constraint.

The manifest is set through an environment variable as JSON with keys being a dependency and values being constraints:

K6_DEPENDENCIES_MANIFEST='{"k6/x/faker": ">=v0.4.4"}' k6 run scripts.js

In this example, if the script only imports k6/x/faker and does not use a use k6 with k6/x/faker ... directive, it will set the version constraint to >=v0.4.4. It will not make any changes if k6/x/faker is not a dependency of the script at all.

Browser module: frameLocator() method #​5487

The browser module now supports frameLocator() on Page, Frame, Locator, and FrameLocator objects. This method creates a locator for working with iframe elements without the need to explicitly switch contexts, making it much easier to interact with embedded content.

Frame locators are particularly valuable when testing applications with nested iframes, as they allow you to chain locators naturally while maintaining readability:

Click to expand example code
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();

  try {
    await page.goto('https://example.com');

    // Locate an iframe and interact with elements inside it
    const frame = page.frameLocator('#payment-iframe');
    await frame.locator('#card-number').fill('4242424242424242');
    await frame.locator('#submit-button').click();

    // Chain frame locators for nested iframes
    const nestedFrame = page
      .frameLocator('#outer-frame')
      .frameLocator('#inner-frame');
    await nestedFrame.locator('#nested-content').click();
  } finally {
    await page.close();
  }
}

This complements existing frame handling methods and provides a more intuitive API for working with iframe-heavy applications.

Browser module: goBack() and goForward() navigation methods #​5494

The browser module now supports page.goBack() and page.goForward() methods for browser history navigation. These methods allow you to navigate the page's history, similar to clicking the browser's back/forward buttons.

Click to expand example code
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();

  try {
    await page.goto('https://example.com');
    await page.goto('https://example.com/page2');
    
    // Navigate back to the previous page
    await page.goBack();
    
    // Navigate forward again
    await page.goForward();
    
    // Both methods support optional timeout and waitUntil parameters
    await page.goBack({ waitUntil: 'networkidle' });
  } finally {
    await page.close();
  }
}
Browser module: Request event handlers #​5481, #​5486

The browser module now supports page.on('requestfailed') and page.on('requestfinished') event handlers, enabling better monitoring and debugging of network activity during browser tests.

The requestfailed event fires when a request fails (network errors, aborts, etc.), while requestfinished fires when a request completes successfully.

Click to expand example code
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();

  // Monitor failed requests
  page.on('requestfailed', (request) => {
    console.log(`Request failed: ${request.url()}`);
  });

  // Monitor successful requests
  page.on('requestfinished', (request) => {
    console.log(`Request finished: ${request.url()}`);
  });

  await page.goto('https://example.com');
  await page.close();
}

These event handlers provide deeper insights into network behavior during browser testing and help identify issues that might not be immediately visible.

Crypto module: PBKDF2 support #​5380

The crypto module now supports PBKDF2 for deriving cryptographic keys from passwords. PBKDF2 is widely used for password hashing and key derivation in security-sensitive applications, and this addition enables testing of systems that use PBKDF2 for authentication or encryption.

For usage examples, check out the one provided in the repository or refer to the documentation.

WebSockets module is now stable #​5586

The websockets module has been promoted to stable status and is now available via the k6/websockets path.
The experimental k6/experimental/websockets module will be removed in a future release. Users should migrate to the stable k6/websockets module.

To migrate, simply update your import statement:

// Old (experimental)
import ws from 'k6/experimental/websockets';

// New (stable)
import ws from 'k6/websockets';

No other changes are required because the API is the same.

Console logging: ArrayBuffer and TypedArray support #​5496

console.log() now properly displays ArrayBuffer and TypedArray objects, making it easier to debug binary data handling in your test scripts. Previously, these types would not display useful information, making debugging difficult when working with binary protocols, file uploads, or WebSocket binary messages.

Click to expand example code
// Log ArrayBuffer - shows detailed byte contents
const buffer = new ArrayBuffer(8);
const view = new Int32Array(buffer);
view[0] = 4;
view[1] = 2;
console.log(buffer);
// Output: ArrayBuffer { [Uint8Contents]: <04 00 00 00 02 00 00 00>, byteLength: 8 }

// Log TypedArrays - shows type, length, and values
const int32 = new Int32Array([4, 2]);
console.log(int32);
// Output: Int32Array(2) [ 4, 2 ]

// Nested objects with TypedArrays
console.log({ v: int32 });
// Output: { v: Int32Array(2) [ 4, 2 ] }

// Complex nested structures
console.log({ 
  name: "test", 
  buffer: buffer, 
  view: int32 
});
// Output: { name: "test", buffer: ArrayBuffer {...}, view: Int32Array(2) [...] }
Configurable TLS version for Experimental Prometheus output #​5537

The experimental Prometheus remote write output now supports configuring the minimum TLS version used for connections. This allows you to meet specific security requirements or compatibility constraints when sending metrics to Prometheus endpoints.

If not set, the default minimum TLS version is 1.3.

K6_PROMETHEUS_RW_TLS_MIN_VERSION=1.3 k6 run script.js -o experimental-prometheus-rw
A new TOTP library k6-totp

A new TOTP (Time-based One-Time Password) library is now available in jslib.k6.io, enabling k6 scripts to generate and validate time-based one-time passwords. This is particularly useful for testing applications that use TOTP-based two-factor authentication (2FA), such as authenticator apps like Google Authenticator or Authy. See the documentation at k6-totp.

Click to expand example code
import http from 'k6/http';
import { TOTP } from 'https://jslib.k6.io/totp/1.0.0/index.js';

export default async function () {
  // Initialize TOTP with your secret key (base32 encoded)
  // The second parameter is the number of digits (typically 6 or 8)
  const totp = new TOTP('GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ', 6);

  // Generate the current TOTP code
  const code = await totp.gen();
  console.log(`Generated TOTP code: ${code}`);

  // Use the TOTP code in authentication
  const response = http.post('https://api.example.com/login', JSON.stringify({
    username: 'user@example.com',
    password: 'password123',
    totpCode: code
  }), {
    headers: { 'Content-Type': 'application/json' }
  });

  // Optionally verify a TOTP code
  const isValid = await totp.verify(code);
  console.log(`Code is valid: ${isValid}`);
}

The library follows the standard TOTP RFC 6238 specification, ensuring compatibility with standard authenticator applications.

Introducing mcp-k6: AI-assisted k6 script writing mcp-k6

mcp-k6 is an experimental Model Context Protocol (MCP) server for k6. Once connected to your AI assistant or MCP-compatible editor (such as Cursor, VS Code, or Claude Desktop), it helps you write better k6 scripts faster and run them with confidence.

With mcp-k6, your AI assistant can:

  • Write accurate scripts: Create up-to-date scripts by referring to embedded k6 documentation and TypeScript definitions to reduce API hallucinations.
  • Validate scripts: Catch syntax errors, missing imports, and export default function declarations before execution.
  • Run tests locally: Execute scripts and review results without leaving your editor.
  • Generate scripts: Create tests from requirements using guided prompts that follow k6 best practices.
  • Convert browser tests: Transform Playwright tests into k6 browser scripts while preserving test logic.

To get started, install mcp-k6 via Docker, Homebrew, or from source, then configure it with your editor. See the documentation for installation instructions and setup guides.

UX improvements and enhancements
  • #​5423 Adds new execution status ExecutionStatusMarkedAsFailed when a test is explicitly marked as failed using exec.test.fail().
  • #​5590 Adds deprecation notice to encourage users to configure their stack when using Cloud CLI commands.
  • #​5607, #​5608 Documentation improvements for Cloud CLI commands.
Bug fixes
  • #​5503 Fixes a memory leak in csv.parse() where each VU created its own copy of CSV data instead of sharing it.
  • #​5425 Fixes CLI validation of summary trend stats to properly accept valid configurations.
  • #​5132 Fixes missing exception when using saltLength: 0 with RSA-PSS sign/verify operations.
  • #​5602 Fixes Config.String() in the OpenTelemetry output to properly display ExporterProtocol.
  • #​5578 Fixes error hiding when the secret value is empty.
  • #​5546 Corrects JSON error position reporting in HTTP requests.
  • #​5526 Fixes browser context cancellation during target attachment to prevent test flakiness.
  • #​5611 Fixes the fallback directory for the binaries cache when it's not possible to get one from the system.
Maintenance and internal improvements
  • #​5603 Upgrades Alpine images in the Dockerfile to the latest versions.
  • #​5498 Makes WaitForEvent mapping more type-safe and consistent by using a typed event name parameter instead of a raw string.
  • #​5561 Improves context-cancellation visibility in browser module by preserving and surfacing deterministic cancellation causes, helping diagnose race conditions and flaky tests.
  • #​5414 Makes make generate command OS-agnostic for cross-platform compatibility.
  • #​5245 Replaces github.com/jhump/protoreflect/desc/protoparse with github.com/bufbuild/protocompile for better protobuf parsing.
  • #​5465 Adds new cloudapi/v6 package with authentication features.
  • #​5573 Optimizes cloud login by running legacy migration only once.
  • #​5570 Moves browser tests into its own test workflow for improved CI performance.
  • #​5560 Refactors browser module mouse options parsing to mapping layer.
  • #​5554 Refactors onAttachedToTarget context done detection for better maintainability.
  • #​5553 Fixes TestFlushMaxSeriesInBatch non-deterministic behavior.
  • #​5489 Addresses frameLocator PR review comments and improves code organization.
  • #​5559 Updates issue auto-assignment to exclude internal team members.
  • #​5536 Configures stale PR workflow to close PRs after 2 months of inactivity.
  • #​5568 Disables flaky tests in CI.
  • #​5531 Improves release template for TypeScript fork synchronization.
  • #​5509, #​5508 Updates error logging from error to debug level for user-unactionable internal issues.
  • #​5621 Disables t.Parallel() on TestCompile for now, to reduce flakiness in CI.
Roadmap

We've started looking into k6 v2! The major release will focus on introducing breaking changes that have accumulated throughout the v1.x series, such as removing deprecated APIs and changing default behaviors. New features will continue to be incrementally released in v1.x minor versions as usual until the v2.0.0 release.

External contributors

A huge thank you to the external contributors who helped during this release: @​LBaronceli, @​baeseokjae, @​chojs23, @​pkalsi97, @​weillercarvalho, @​ariasmn, @​rahulmedicharla, @​janHildebrandt98 and @​shota3506! 🙏

v1.5.0

Compare Source

k6 1.5.0 is here 🎉! This release includes:

  • Changes in the browser module:
    • page.waitForEvent() for event-based synchronization with page events.
    • locator.pressSequentially() for character-by-character typing simulation.
  • Improved debugging with deep object logging in console.log().
  • Extended WebSocket support with close code and reason information.
  • Enhanced extension ecosystem with custom subcommands and DNS resolver access.
  • URL-based secret management for external secret services.
  • New machine-readable summary format for test results.

Breaking changes

As per our stability guarantees, breaking changes across minor releases are allowed only for experimental features.

New features

page.waitForEvent() #​5478

The browser module now supports page.waitForEvent(), which blocks the caller until a specified event is captured.

If a predicate is provided, it waits for an event that satisfies the predicate. This method is particularly valuable for testing scenarios where you need to synchronize your test flow with specific browser or page events before proceeding with the next action.

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();

  // Wait for a console message containing specific text
  const msgPromise = page.waitForEvent('console', msg => msg.text().includes('hello'));
  await page.evaluate(() => console.log('hello world'));
  const msg = await msgPromise;
  console.log(msg.text());
  // Output: hello world

  // Wait for a response from a specific URL with timeout
  const resPromise = page.waitForEvent('response', {
    predicate: res => res.url().includes('/api/data'),
    timeout: 5000,
  });
  await page.click('button#fetch-data');
  const res = await resPromise;

  await page.close();
}

Event-driven synchronization is vital for test reliability, especially when dealing with asynchronous operations where timing is unpredictable. This is more robust than using fixed delays and helps avoid flaky tests.

locator.pressSequentially() #​5457

The browser module now supports locator.pressSequentially(), which types text character by character, firing keyboard events (keydown, keypress, keyup) for each character. This method is essential for testing features that depend on gradual typing to trigger specific behaviors, such as autocomplete suggestions, real-time input validation per character, or dynamic character counters.

The method supports a configurable delay between keystrokes, enabling you to simulate realistic typing speeds and test time-dependent input handlers:

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();

  try {
    await page.goto('https://test.k6.io/browser.php');

    // Type text character by character
    const searchInput = page.locator('#text1');
    await searchInput.pressSequentially('Hello World');

    // Type with delay to simulate realistic typing speed
    await searchInput.clear();
    await searchInput.pressSequentially('test query', { delay: 100 });
  } finally {
    await page.close();
  }
}

This complements existing text input methods: locator.fill() for simple form filling, locator.type() for gradual typing without keyboard events, and now pressSequentially for character-by-character typing with full keyboard event firing.

Thank you, @​rajan2345, for the contribution 🎉

console.log() Deep Object Logging #​5460

console.log() now properly traverses and displays complex JavaScript structures, including functions, classes, and circular references. Previously, Sobek's JSON marshaling would lose nested functions, classes, and other non-serializable types, making debugging painful.

Objects with mixed function and class properties are now properly displayed:

console.log({
  one: class {},
  two: function() {}
});
// Before: {}
// After:  {"one":"[object Function]","two":"[object Function]"}

Nested arrays and objects with functions are now fully traversed:

console.log([
  { handler: class {} },
  { data: [1, 2, class {}] }
]);
// Before: [{},{"data":[1,2,null]}]
// After:  [{"handler":"[object Function]"},{"data":[1,2,"[object Function]"]}]

Complex objects with multiple property types are properly preserved:

console.log({
  a: [1, 2, 3],
  b: class {},
  c: () => {},
  d: function() {},
  e: [1, () => {}, function() {}, class {}, 2]
});
// Before: {"a":[1,2,3],"e":[1,null,null,null,2]}
// After:  {
//   "a":[1,2,3],
//   "b":"[object Function]",
//   "c":"[object Function]",
//   "d":"[object Function]",
//   "e":[1,"[object Function]","[object Function]","[object Function]",2]
// }

Circular references are now properly detected and marked:

const obj = {
  fn: function() {},
  foo: {}
};
obj.foo = obj;

console.log(obj);
// Before: [object Object]
// After:  {"fn":"[object Function]","foo":"[Circular]"}

This improvement makes debugging k6 test scripts significantly easier when working with API responses, event handlers, and complex state objects.

experimental/websockets - Close Code and Reason Support #​5376

The experimental WebSockets module now supports sending close codes and reasons when closing connections, and properly captures close event information. This is essential for testing WebSocket
implementations that rely on specific close codes to determine whether a connection was closed normally or due to an error.

import ws from 'k6/experimental/websockets';

export default function () {
  const socket = ws.connect('ws://example.com', (socket) => {
    socket.on('close', (data) => {
      console.log(`Connection closed with code: ${data.code}, reason: ${data.reason}`);
      // Output: Connection closed with code: 1000, reason: Normal closure
    });
  });

  // Close with code and reason
  socket.close(1000, 'Normal closure');
}

Thanks, @​etodanik, for the contribution 🎉

Subcommand Extension Support #​5399

Extensions can now register custom subcommands under the k6 x namespace, enabling custom command-line tools that integrate seamlessly with k6. This provides a consistent and discoverable way for extensions to offer specialized CLI utilities while maintaining k6's familiar command structure.

Extensions can now define custom commands like:

k6 x my-tool --help
k6 x debug --inspect

This integration pattern allows extension authors to provide powerful tooling that feels native to the k6 ecosystem.

DNS Resolver Access #​5421

Extensions can now access k6's DNS resolver for custom DNS handling and networking extensions. The resolver respects k6's configuration including hosts overrides, custom DNS servers, and DNS caching settings. This enables extensions to use it directly instead of having to reproduce the functionality. Which also makes them work the same way as native modules.

Machine-Readable Summary Format #​5338

A new machine-readable summary format for the end-of-test summary is now available, providing structured, programmatic shapes via --summary-export and handleSummary(). This format is designed for easier integration with external systems and analytics pipelines.

The new format is currently opt-in via the --new-machine-readable-summary flag or K6_NEW_MACHINE_READABLE_SUMMARY environment variable, and will become the default in k6 v2:

k6 run script.js --new-machine-readable-summary --summary-export=summary.json

This makes it easier to integrate k6 results into CI/CD pipelines, dashboards, and custom analysis tools.

URL-Based Secret Management #​5413

The secret management system now supports URL-based secret sources, allowing k6 to fetch secrets from HTTP endpoints. This lets users implement a simple HTTP API to provide secrets to a test. There is a mock implementation, but no particular production-ready implementation is provided at this time. In the future, there is potential for proxies to other systems, including HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault.

UX improvements and enhancements

  • #​5458 Adds link to k6 extensions list in README for better discoverability.
  • #​5366 Adds multi-source secret example for better documentation of secret management patterns.

Bug fixes

  • #​5374 Fixes getBy* selectors when using quotes inside element names.
  • #​5477 Fixes retry mechanism when frame has been detached.
  • #​5461 Fixes panic when using nil page.on handlers.
  • #​5401 Fixes panic when assigning to nil headers and cookies when the host is not found. Thanks, @​chojs23, for the contribution 🎉
  • #​5379 Fixes browsers not being stopped in tests due to EndIteration.
  • #​5439 Fixes loading files with spaces.
  • #​5406 Fixes error messages after Sobek/goja changes.
  • #​5381 Fixes version command JSON output for output extensions.
  • #​5358 Fixes sending correct data when using ArrayViews in experimental/websockets.
  • #​5488 Fixes a goroutine leak when performing CDP requests.

Maintenance and internal improvements

  • #​5464 Adds ExecutionStatusMarkedAsFailed status for improved test execution tracking.
  • #​5467 Refactors span error recording to avoid boilerplate code.
  • #​5438 Unblocks the release workflow for package publishing.
  • #​5436 Optimizes browser module allocations and improves CI stability.
  • #​5411 Extends base config and stops updating go.mod toolchain.
  • #​5408 Removes redundant GitHub Actions rule.
  • #​5415 Updates Sobek dependency to latest version.
  • #​5392 Updates OpenTelemetry proto module to v1.9.0.
  • #​5357 Refactors browser module task queue usage.
  • #​5378 Fixes TestNavigationSpanCreation test in the browser module.
  • #​5482 Fixes tests and subcommand handling in the version command.
  • #​5255 Updates gRPC module to v1.77.0.
  • #​5506 Updates xk6-redis to v0.3.6.
  • #​5473 Updates compression library to v1.18.2.
  • #​5505 Removes close call in integration tests.
  • #​5517 Removes SECURITY.md to sync with Grafana's org-wide security policy documentation.
  • #​5528 Resolves CVE-2025-61729. Thanks, @​SimKev2, for the contribution 🎉

Roadmap

Deprecation of First Input Delay (FID) Web Vital

Following the official web vitals guidance, 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.

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.

Action required

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.

// Instead of relying on FID
export const options = {
  thresholds: {
    // 'browser_web_vital_fid': ['p(95)<100'], // Deprecated
    'browser_web_vital_inp': ['p(95)<200'], // Use INP instead
  },
};

This change ensures k6 browser testing stays aligned with modern web performance best practices and Core Web Vitals standards.

v1.4.2

Compare Source

k6 v1.4.2 is here 🎉!

This is a patch release that includes:

v1.4.1

Compare Source

k6 v1.4.1 is here 🎉!

This is a patch release that includes:

  • #​5428 Reverts "Use new expect() syntax in script templates"

We'll re-introduce assertion-based templates down the road when the integration is seamless.

v1.4.0

Compare Source

k6 v1.4.0 is here 🎉! This release includes:

  • OpenTelemetry output graduated from experimental to stable status.
  • Changes in the Browser module:
    • page.waitForRequest for waiting on specific HTTP requests.
    • QueryAll methods now return elements in DOM order.
    • locator.evaluate and locator.evaluateHandle for executing JavaScript code in the page context with access to the matching element.
    • page.unroute(url) and page.unrouteAll for removing routes registered with page.route.

Breaking changes

As per our stability guarantees, breaking changes across minor releases are allowed only for experimental features.

Breaking changes for experimental modules
  • #​5164 OpenTelemetry output now exports rate metrics as a single counter with zero/nonzero labels instead of separate metrics.
  • #​5333 OpenTelemetry output configuration: K6_OTEL_EXPORTER_TYPE is deprecated in favor of K6_OTEL_EXPORTER_PROTOCOL to align with OpenTelemetry standards.
Breaking changes for undefined behaviours
  • #​5320, #​5239, #​5342 Automatic extension resolution now only inspects ES module import statements and no longer supports CommonJS require() calls. CommonJS require() calls are dynamic, and it is not possible to know for certain if they will be called, or if they will be called with static strings - the only way they were even previously loaded. This functionality was a quirk of the previous implementation and had numerous problems. Additionally, use k6 directives are now only recognized when they appear at the beginning of files (after optional shebang and whitespace/comments). This was the original intention, but due to implementation bugs, it did not accurately reflect what was happening.

New features

OpenTelemetry output graduation #​5334

The OpenTelemetry output has graduated from experimental status and is now available as a stable output using the name opentelemetry. This change makes OpenTelemetry the recommended vendor-agnostic solution for exporting k6 telemetry data.

You can now use the stable output name in your k6 commands:

### Previous experimental usage (still supported for backward compatibility)
k6 run --out experimental-opentelemetry script.js

### New stable usage
k6 run --out opentelemetry script.js

The experimental-opentelemetry name will continue to work for backward compatibility for now but it's deprecated and we might remove it in future versions. We recommend migrating to use the new opentelemetry name.

page.waitForRequest #​5330

The browser module now supports page.waitForRequest(), which allows you to wait for HTTP requests that match specific URL patterns during browser automation. This method is particularly valuable for testing scenarios where you need to ensure specific network requests are initiated before proceeding with test actions.

The method supports multiple URL pattern matching strategies:

// Wait for exact URL match
const requestPromise = page.waitForRequest('https://api.example.com/data');
await page.click('button[data-testid="load-data"]');
const request = await requestPromise;

// Wait for regex pattern match
await page.waitForRequest(/\/api\/.*\.json$/);

// Use with Promise.all for coordinated actions
await Promise.all([
  page.waitForRequest('https://api.example.com/user-data'),
  page.click('button[data-testid="load-user-data"]')
]);

This complements the existing page.waitForResponse() method by focusing on HTTP requests rather than responses, providing more granular control over network-dependent test scenarios.

page.unroute(url) and page.unrouteAll() #​5223

The browser module now supports page.unroute(url) and page.unrouteAll(), allowing you to remove routes previously registered with page.route.

Example usage:

await page.route(/.*\/api\/pizza/, function (route) {
  console.log('Modifying request to /api/pizza');
  route.continue({
    postData: JSON.stringify({
      customName: 'My Pizza',
    }),
  });
});
...

await page.unroute(/.*\/api\/pizza/); // The URL needs to be exactly the same as the one used in the call to the `route` function
await page.route(/.*\/api\/pizza/, function (route) {
  console.log('Modifying request to /api/pizza');
  route.continue({
    postData: JSON.stringify({
      customName: 'My Pizza',
    }),
  });
});
...

await page.unrouteAll();
locator.evaluate and locator.evaluateHandle #​5306

The browser module now supports locator.evaluate and locator.evaluateHandle, allowing you to execute JavaScript code in the page context with access to the matching element. The only difference between evaluate and evaluateHandle is that evaluateHandle returns a JSHandle.

Example usage:

await check(page, {
  'calling evaluate': async p => {
    const n = await p.locator('#pizza-name').evaluate(pizzaName => pizzaName.textContent);
    return n == 'Our recommendation:';
  }
});

await check(page, {
  'calling evaluate with arguments': async p => {
    const n = await p.locator('#pizza-name').evaluate((pizzaName, extra) => pizzaName.textContent + extra, ' Super pizza!');
    return n == 'Our recommendation: Super pizza!';
  }
});
const jsHandle = await page.locator('#pizza-name').evaluateHandle((pizzaName) => pizzaName);

const obj = await jsHandle.evaluateHandle((handle) => {
  return { innerText: handle.innerText };
});
console.log(await obj.jsonValue()); // {"innerText":"Our recommendation:"}
New officially supported k6 DNS extension

The xk6-dns extension is now officially supported in k6 OSS and k6 Cloud. You can import k6/x/dns directly in your scripts thanks to automatic extension resolution, with no custom build required.

Use it to perform DNS resolution testing as part of your tests: resolve names via custom or system DNS, measure resolution latency and errors, validate records before HTTP steps, compare resolvers, and even load test DNS servers in end‑to‑end scenarios.

For example:

import dns from 'k6/x/dns';

export default function () {
  const answer = dns.resolve('grafana.com', { recordType: 'A' });
  console.log(answer.records.map(({ address }) => address).join(', '));
}

The extension currently supports A and AAAA record lookups. If you would like to see additional record types supported, please consider contributing to the extension.

Automatic extension resolution improvements #​5320, #​5239, #​5342, #​5332, #​5240

Automatic extension resolution has been completely reimplemented to use k6's internal module loader instead of the external k6deps/esbuild pipeline. This change brings significant improvements in reliability and maintainability.

As part of the rewrite, a few issues and unintended features were found, namely:

  1. Trying to follow require calls, which, due to their dynamic nature, don't work particularly stably. That is, depending on where and how the require call was used, k6 might decide whether it is needed or not. And it definitely doesn't work when using actual string variables. Support for CommonJS is primarily for backward compatibility, so after an internal discussion, we opted not to support it at all. We could bring this back until v2, if there is enough interest. However, in the long term, it is intended that this not be part of k6.
  2. "use k6 with ..." directives were parsed from the whole file instead of just the beginning, which leads to numerous problems, and was not the intended case. As such, they are now only parsed at the beginning of files (not just the main one) with potential empty lines and comments preceding them.

Example:

// main.js
"use k6 with k6/x/faker"
import { faker } from 'k6/x/faker';
import { helper } from './utils.js';

export default function() {
  console.log(faker.name());
  helper();
}

Or, an example using the directive with CommonJS

// utils.js
"use k6 with k6/x/redis"
const redis = require('k6/x/redis');

exports.helper = function() {
  // Use redis extension
}

In this example, k6 will detect both k6/x/faker and k6/x/redis extensions from the use k6 directives in both files and provision a binary that includes both extensions if needed.

Other fixes this brings are:

  1. Fixes for path related issues (irregardless of usage of the feature) on windows, especially between drives. It is possible there were problems on other OSes that were just not reported. #​5176

  2. Syntax errors were not reported as such, as the underlying esbuild parsing will fail, but won't be handled well. #​5127, #​5104

  3. Propagating exit codes from a sub-process running the new k6. This lets you use the result of the exit code.

UX improvements and enhancements

  • #​5307 QueryAll methods now return elements in DOM order. Thank you, @​shota3506, for the contribution.
  • #​5159 Simplifies warning message for legacy config files.
  • #​5343 Explictly marks the option's default values.

Bug fixes

  • #​5242 Fixes cleanup errors on Windows for browser tests.
  • #​5246 Fixes the support for TypeScript source code from stdin.
  • #​5322 Fixes browser.newPageInContext bug where pages created in a non-existing browser context.

Maintenance and internal improvements

v1.3.0

Compare Source

k6 v1.3.0 is here 🎉! This release includes:

  • Browser module gets:
    • locator.locator, locator.contentFrame, and FrameLocator.locator for powerful locator chaining and iframe handling.
    • locator|frame|FrameLocator.getBy* for targeting elements without relying on brittle CSS selectors.
    • locator.filter for filtering locators for more precise element targeting.
    • locator.boundingBox for retrieving element geometry.
    • page.waitForResponse for waiting on specific HTTP responses.

Deprecations

A new summary mode disabled has been introduced to replace the "no summary" option #​5118

The --no-summary flag and its corresponding environment variable K6_NO_SUMMARY have been deprecated in favor of
the new disabled summary mode. This change unifies the configuration experience for controlling the end-of-test summary.

You can now disable the end-of-test summary with either --summary-mode=disabled or K6_SUMMARY_MODE=disabled.

The legacy summary mode has been deprecated [#​5138](h

Configuration

📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

Need help?

You can ask for more help in the following Slack channel: #proj-renovate-self-hosted. In that channel you can also find ADR and FAQ docs in the Resources section.

@renovate-sh-app
Copy link
Contributor Author

renovate-sh-app bot commented Nov 10, 2025

ℹ Artifact update notice

File name: extensions/xk6-judge/go.mod

In order to perform the update(s) described in the table above, Renovate ran the go get command, which resulted in the following additional change(s):

  • 21 additional dependencies were updated

Details:

Package Change
github.com/cenkalti/backoff/v5 v5.0.2 -> v5.0.3
github.com/dlclark/regexp2 v1.11.4 -> v1.11.5
github.com/evanw/esbuild v0.25.8 -> v0.25.10
github.com/grafana/sobek v0.0.0-20250723111835-dd8a13f0d439 -> v0.0.0-20251124090928-9a028a30ff58
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 -> v2.27.2
go.opentelemetry.io/otel v1.37.0 -> v1.38.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 -> v1.38.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0 -> v1.38.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 -> v1.38.0
go.opentelemetry.io/otel/metric v1.37.0 -> v1.38.0
go.opentelemetry.io/otel/sdk v1.37.0 -> v1.38.0
go.opentelemetry.io/otel/trace v1.37.0 -> v1.38.0
go.opentelemetry.io/proto/otlp v1.7.1 -> v1.8.0
golang.org/x/net v0.43.0 -> v0.46.0
golang.org/x/sys v0.35.0 -> v0.37.0
golang.org/x/text v0.28.0 -> v0.30.0
golang.org/x/time v0.12.0 -> v0.14.0
google.golang.org/genproto/googleapis/api v0.0.0-20250728155136-f173205681a0 -> v0.0.0-20250825161204-c5933d9347a5
google.golang.org/genproto/googleapis/rpc v0.0.0-20250728155136-f173205681a0 -> v0.0.0-20250825161204-c5933d9347a5
google.golang.org/grpc v1.74.2 -> v1.75.0
google.golang.org/protobuf v1.36.7 -> v1.36.10

@renovate-sh-app renovate-sh-app bot force-pushed the renovate/go.k6.io-k6-1.x branch from c5fcdd6 to 577a581 Compare November 13, 2025 12:42
@renovate-sh-app renovate-sh-app bot changed the title fix(deps): update module go.k6.io/k6 to v1.3.0 fix(deps): update module go.k6.io/k6 to v1.4.0 Nov 13, 2025
@renovate-sh-app renovate-sh-app bot force-pushed the renovate/go.k6.io-k6-1.x branch from 577a581 to ecd2690 Compare November 23, 2025 18:20
@renovate-sh-app renovate-sh-app bot changed the title fix(deps): update module go.k6.io/k6 to v1.4.0 fix(deps): update module go.k6.io/k6 to v1.4.1 Nov 23, 2025
@renovate-sh-app renovate-sh-app bot force-pushed the renovate/go.k6.io-k6-1.x branch from ecd2690 to 3c6bdd5 Compare November 27, 2025 16:16
@renovate-sh-app renovate-sh-app bot changed the title fix(deps): update module go.k6.io/k6 to v1.4.1 fix(deps): update module go.k6.io/k6 to v1.4.2 Nov 27, 2025
@renovate-sh-app renovate-sh-app bot force-pushed the renovate/go.k6.io-k6-1.x branch from 3c6bdd5 to 4c03f1f Compare January 8, 2026 20:17
@renovate-sh-app renovate-sh-app bot changed the title fix(deps): update module go.k6.io/k6 to v1.4.2 fix(deps): update module go.k6.io/k6 to v1.5.0 Jan 8, 2026
@renovate-sh-app
Copy link
Contributor Author

renovate-sh-app bot commented Jan 8, 2026

ℹ️ Artifact update notice

File name: extensions/xk6-judge/go.mod

In order to perform the update(s) described in the table above, Renovate ran the go get command, which resulted in the following additional change(s):

  • 16 additional dependencies were updated

Details:

Package Change
github.com/cenkalti/backoff/v5 v5.0.2 -> v5.0.3
github.com/dlclark/regexp2 v1.11.4 -> v1.11.5
github.com/evanw/esbuild v0.25.8 -> v0.27.2
github.com/grafana/sobek v0.0.0-20250723111835-dd8a13f0d439 -> v0.0.0-20260121195222-d8d9202018c5
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 -> v2.27.2
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 -> v1.38.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0 -> v1.38.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 -> v1.38.0
go.opentelemetry.io/proto/otlp v1.7.1 -> v1.9.0
golang.org/x/net v0.45.0 -> v0.49.0
golang.org/x/text v0.29.0 -> v0.33.0
golang.org/x/time v0.12.0 -> v0.14.0
google.golang.org/genproto/googleapis/api v0.0.0-20250728155136-f173205681a0 -> v0.0.0-20251022142026-3a174f9686a8
google.golang.org/genproto/googleapis/rpc v0.0.0-20250728155136-f173205681a0 -> v0.0.0-20251022142026-3a174f9686a8
google.golang.org/grpc v1.74.2 -> v1.77.0
google.golang.org/protobuf v1.36.7 -> v1.36.11

@renovate-sh-app renovate-sh-app bot force-pushed the renovate/go.k6.io-k6-1.x branch 2 times, most recently from 1c85c25 to f444da5 Compare February 13, 2026 11:46
@renovate-sh-app renovate-sh-app bot changed the title fix(deps): update module go.k6.io/k6 to v1.5.0 fix(deps): update module go.k6.io/k6 to v1.6.0 Feb 13, 2026
@renovate-sh-app renovate-sh-app bot force-pushed the renovate/go.k6.io-k6-1.x branch from f444da5 to 6980b4e Compare February 19, 2026 11:43
@renovate-sh-app renovate-sh-app bot changed the title fix(deps): update module go.k6.io/k6 to v1.6.0 fix(deps): update module go.k6.io/k6 to v1.6.1 Feb 19, 2026
| datasource | package     | from   | to     |
| ---------- | ----------- | ------ | ------ |
| go         | go.k6.io/k6 | v1.2.3 | v1.6.1 |


Signed-off-by: renovate-sh-app[bot] <219655108+renovate-sh-app[bot]@users.noreply.github.com>
@renovate-sh-app renovate-sh-app bot force-pushed the renovate/go.k6.io-k6-1.x branch from 6980b4e to 8271891 Compare February 20, 2026 14:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants