@e2e-dev/web 0.15.1-nightly-20261015074742 → 0.15.1

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/dist/.build.json CHANGED
@@ -1 +1 @@
1
- {"version":"0.15.1-nightly-20261015074742"}
1
+ {"version":"0.15.1"}
@@ -98,10 +98,10 @@ export declare class AttemptSession {
98
98
  /**
99
99
  * Emulates the attempt's media on each tab as it appears, so a tab the app
100
100
  * opens itself follows a test's change too, on a persistent context as
101
- * well, where the engine sets no context options. It paints with the
102
- * context's configured values first: Playwright emulates per page, so a
103
- * test's change reaches it once it exists. A tab the attempt opens awaits
104
- * the same work in `ensurePage`; a tab the app opens is not awaited.
101
+ * well, where the engine sets no context options. Playwright emulates per
102
+ * page, so a test's change reaches it once it exists: its scripts may read
103
+ * the context's configured values until then. A tab the attempt opens
104
+ * awaits the same work in `ensurePage`; a tab the app opens is not awaited.
105
105
  */
106
106
  private watchPages;
107
107
  /** Restarts the document while retaining this context's storage. */
@@ -254,10 +254,10 @@ export class AttemptSession {
254
254
  /**
255
255
  * Emulates the attempt's media on each tab as it appears, so a tab the app
256
256
  * opens itself follows a test's change too, on a persistent context as
257
- * well, where the engine sets no context options. It paints with the
258
- * context's configured values first: Playwright emulates per page, so a
259
- * test's change reaches it once it exists. A tab the attempt opens awaits
260
- * the same work in `ensurePage`; a tab the app opens is not awaited.
257
+ * well, where the engine sets no context options. Playwright emulates per
258
+ * page, so a test's change reaches it once it exists: its scripts may read
259
+ * the context's configured values until then. A tab the attempt opens
260
+ * awaits the same work in `ensurePage`; a tab the app opens is not awaited.
261
261
  */
262
262
  watchPages(context) {
263
263
  context.on('page', (page) => {
package/dist/browser.d.ts CHANGED
@@ -223,6 +223,10 @@ export interface Browser extends Expectable<BrowserExpectation> {
223
223
  readonly keyboard: {
224
224
  /** Sends one key. */
225
225
  press(key: string): Promise<void>;
226
+ /** Holds one key until up; repeated down calls send a repeat event. */
227
+ down(key: string): Promise<void>;
228
+ /** Releases a held key. */
229
+ up(key: string): Promise<void>;
226
230
  /** Types plain text. */
227
231
  type(text: string): Promise<void>;
228
232
  };
package/dist/browser.js CHANGED
@@ -350,6 +350,8 @@ export function createBrowserFixture(surface, context) {
350
350
  }, 'test-code');
351
351
  },
352
352
  keyboard: {
353
+ down: (key) => surface.guard(context.operation(), 'keyboard.down', () => surface.requirePage().keyboard.down(key), classifyInputError),
354
+ up: (key) => surface.guard(context.operation(), 'keyboard.up', () => surface.requirePage().keyboard.up(key), classifyInputError),
353
355
  press: (key) => surface.guard(context.operation(), 'keyboard.press', () => surface.requirePage().keyboard.press(key), classifyInputError),
354
356
  type: (text) => surface.guard(context.operation(), 'keyboard.type', () => surface.requirePage().keyboard.type(text), classifyInputError),
355
357
  },
@@ -387,7 +389,7 @@ export function createBrowserFixture(surface, context) {
387
389
  emulateMedia: { ...action, label: (media) => mediaLabel(media) },
388
390
  onDialog: action,
389
391
  waitForDownload: { ...action, timeout: (_trigger, options) => options?.timeout },
390
- keyboard: { press: { ...action, label: (key) => key }, type: { ...action, label: (text) => `${text.length} chars` } },
392
+ keyboard: { down: { ...action, label: (key) => key }, up: { ...action, label: (key) => key }, press: { ...action, label: (key) => key }, type: { ...action, label: (text) => `${text.length} chars` } },
391
393
  mouse: { move: action, wheel: action, down: action, up: action },
392
394
  });
393
395
  }
@@ -98,6 +98,22 @@ export const readSemanticsFunction = (element, options) => {
98
98
  return value;
99
99
  };
100
100
  };
101
+ /** Concrete WAI-ARIA roles, excluding abstract roles that cannot label an element. */
102
+ const ARIA_ROLES = [
103
+ 'alert', 'alertdialog', 'application', 'article', 'banner', 'blockquote', 'button', 'caption',
104
+ 'cell', 'checkbox', 'code', 'columnheader', 'combobox', 'complementary', 'contentinfo', 'definition',
105
+ 'deletion', 'dialog', 'directory', 'document', 'emphasis', 'feed', 'figure', 'form',
106
+ 'generic', 'grid', 'gridcell', 'group', 'heading', 'img', 'insertion', 'link',
107
+ 'list', 'listbox', 'listitem', 'log', 'main', 'mark', 'marquee', 'math',
108
+ 'meter', 'menu', 'menubar', 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'navigation', 'none',
109
+ 'note', 'option', 'paragraph', 'presentation', 'progressbar', 'radio', 'radiogroup', 'region',
110
+ 'row', 'rowgroup', 'rowheader', 'scrollbar', 'search', 'searchbox', 'separator', 'slider',
111
+ 'spinbutton', 'status', 'strong', 'subscript', 'superscript', 'switch', 'tab', 'table',
112
+ 'tablist', 'tabpanel', 'term', 'textbox', 'time', 'timer', 'toolbar', 'tooltip',
113
+ 'tree', 'treegrid', 'treeitem',
114
+ ];
115
+ /** ARIA uses the first recognized token, then native semantics if none is recognized. */
116
+ const explicitRole = memoized((el) => (el.getAttribute('role') ?? '').split(/[ \t\n\f\r]+/).find((role) => ARIA_ROLES.indexOf(role) !== -1) ?? null);
101
117
  /**
102
118
  * True when an element carries a name of its own (HTML-AAM: `aria-label`,
103
119
  * `aria-labelledby`, or `title`). A `<form>` or `<section>` is a landmark
@@ -137,11 +153,10 @@ export const readSemanticsFunction = (element, options) => {
137
153
  NON_HOST_TAGS.indexOf(el.tagName.toLowerCase()) === -1 &&
138
154
  !(el.parentElement instanceof HTMLElement && el.parentElement.isContentEditable);
139
155
  const implicitRole = memoized((el) => {
140
- const explicit = el.getAttribute('role');
141
- if (explicit !== null && explicit.trim() !== '') {
142
- const first = explicit.trim().split(/\s+/)[0] ?? null;
156
+ const explicit = explicitRole(el);
157
+ if (explicit !== null) {
143
158
  // The vocabulary spells ARIA's `img` as `image`.
144
- return first === 'img' ? 'image' : first;
159
+ return explicit === 'img' ? 'image' : explicit;
145
160
  }
146
161
  // Ahead of the tag: an editor's host is the control, whatever landmark or
147
162
  // structure its tag would otherwise be.
@@ -225,7 +240,7 @@ export const readSemanticsFunction = (element, options) => {
225
240
  // A grid's cells are the interactive kind, as Playwright reads them.
226
241
  case 'td': {
227
242
  const table = el.closest('table');
228
- const tableRole = table?.getAttribute('role')?.trim().split(/\s+/)[0];
243
+ const tableRole = table === null ? null : explicitRole(table);
229
244
  return tableRole === 'grid' || tableRole === 'treegrid' ? 'gridcell' : 'cell';
230
245
  }
231
246
  case 'th': {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@e2e-dev/web",
3
- "version": "0.15.1-nightly-20261015074742",
3
+ "version": "0.15.1",
4
4
  "description": "Web engine for e2e agentic end-to-end testing, built on Playwright",
5
5
  "keywords": [
6
6
  "e2e",
@@ -50,11 +50,11 @@
50
50
  "playwright-core": "1.64.0"
51
51
  },
52
52
  "peerDependencies": {
53
- "e2e": "0.21.1-nightly-20261015074742"
53
+ "e2e": ">=0.18.0 <1"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@types/node": "26.6.2",
57
- "e2e": "0.21.1-nightly-20261015074742",
57
+ "e2e": "0.21.1",
58
58
  "@types/pngjs": "6.0.5",
59
59
  "pngjs": "7.0.0",
60
60
  "typescript": "7.0.2",