Skip to content

k6/html: Tester callback (filter/is/not) is typed with Element but k6 passes a Selection #6088

Description

@TheOneFromNorway

Brief summary

The Tester interface is the callback type for Selection.filter(), Selection.is() and Selection.not(). It declares the second parameter as an Element:

export interface Tester {
    (index: number, element: Element): boolean;
}

At runtime, however, k6/html invokes these callbacks with a Selection, not an Element. Because Selection does not expose Element-only members such as querySelector, code that type-checks against these definitions throws at runtime:

TypeError: Object has no member 'querySelector'

k6 version

v2.0.0

OS

all

Docker version and image (if applicable)

No response

Steps to reproduce the problem

With test plan

import { parseHTML } from 'k6/html';

export default function () {
  const doc = parseHTML('<div class="c"><a href="/x">John</a></div>');

  doc.find('div.c').filter((_i, el) => el.querySelector('a[href]') != null);
}

you already see the issue. The code compiles cleanly (TS thinks el is an Element, which has querySelector) but throws at runtime because el is actually a Selection and you get
TypeError: Object has no member 'querySelector'

Why this is a type bug (not version-specific)

  • The official Selection.filter() documentation example uses el.text() — a Selection method — inside the callback:
    https://grafana.com/docs/k6/latest/javascript-api/k6-html/selection/selection-filter/
  • The definitions are internally inconsistent: Mapper (the Selection.map() callback, which also receives a Selection) is already correctly typed with Selection, while Tester is not.
  • Reproduces identically on k6 v1.3.0 and v2.0.0, so it is independent of the k6 binary version.

Expected behaviour

Type Tester callback's second parameter as a Selection:

export interface Tester {
    (index: number, selection: Selection): boolean;
}

Actual behaviour

Type the Tester callback's second parameter is typed as an Element even though it is not

Metadata

Metadata

Assignees

Labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions