@allwright.dev/core 0.1.1 → 0.1.3

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/bootstrap.js CHANGED
@@ -12,7 +12,7 @@ const ALLWRIGHT_HOME_ENV_VAR = "ALLWRIGHT_HOME";
12
12
  const ALLWRIGHT_REPOSITORY_ENV_VAR = "ALLWRIGHT_REPOSITORY";
13
13
  const ALLWRIGHT_VERSION_ENV_VAR = "ALLWRIGHT_VERSION";
14
14
  const DEFAULT_RELEASE_REPOSITORY = "allwright-dev/allwright";
15
- const DEFAULT_RELEASE_VERSION = "0.1.1";
15
+ const DEFAULT_RELEASE_VERSION = "0.1.3";
16
16
  const STARTUP_TIMEOUT_MS = 20_000;
17
17
  const PING_TIMEOUT_MS = 1_000;
18
18
  const PROTO_ROOT = fileURLToPath(new URL("../proto/", import.meta.url));
package/dist/index.d.ts CHANGED
@@ -18,3 +18,4 @@ export declare function launchBrowser(): Promise<Browser>;
18
18
  export declare function launchBrowser(options: ResolveConfigOptions): Promise<Browser>;
19
19
  export declare function launchBrowser(browserKind: BrowserKind, options?: LaunchOptions): Promise<Browser>;
20
20
  export { BrowserImpl, BrowserTypeImpl, PageImpl };
21
+ export type { TextMatcher, TextOptions, RoleOptions, LocatorFilterOptions } from "./web-locators.js";
package/dist/locator.d.ts CHANGED
@@ -1,5 +1,6 @@
1
+ import { WebLocatorBuilders, type LocatorFilterOptions } from "./web-locators.js";
1
2
  import type { ClickResult, CommandOptions, CountResult, ElementResult, FillResult, HighlightOptions, HighlightResult, Locator, LocatorInfo, Page, PressOptions, PressResult, TextResult, WaitForSelectorOptions, WaitForSelectorResult } from "./types.js";
2
- export declare class LocatorImpl implements Locator {
3
+ export declare class LocatorImpl extends WebLocatorBuilders implements Locator {
3
4
  readonly page: Page;
4
5
  readonly selector: string;
5
6
  constructor(input: LocatorInfo);
@@ -13,5 +14,10 @@ export declare class LocatorImpl implements Locator {
13
14
  textContent(options?: CommandOptions): Promise<TextResult>;
14
15
  innerText(options?: CommandOptions): Promise<TextResult>;
15
16
  waitFor(options?: WaitForSelectorOptions): Promise<WaitForSelectorResult>;
16
- locator(selector: string): Locator;
17
+ not(other: Locator): Locator;
18
+ filter(options?: LocatorFilterOptions): Locator;
19
+ nth(index: number): Locator;
20
+ first(): Locator;
21
+ last(): Locator;
22
+ locator(selector: string, options?: LocatorFilterOptions): Locator;
17
23
  }
package/dist/locator.js CHANGED
@@ -1,8 +1,10 @@
1
+ import { WebLocatorBuilders, semanticSelector } from "./web-locators.js";
1
2
  import { chainSelectorForTransport } from "./selectors.js";
2
- export class LocatorImpl {
3
+ export class LocatorImpl extends WebLocatorBuilders {
3
4
  page;
4
5
  selector;
5
6
  constructor(input) {
7
+ super();
6
8
  this.page = input.page;
7
9
  this.selector = input.selector;
8
10
  }
@@ -36,10 +38,30 @@ export class LocatorImpl {
36
38
  async waitFor(options = {}) {
37
39
  return this.page.waitForSelector(this.selector, options);
38
40
  }
39
- locator(selector) {
40
- return new LocatorImpl({
41
+ not(other) {
42
+ if (other.page !== this.page)
43
+ throw new Error('Excluded locators must belong to the same page');
44
+ return this.locator(semanticSelector({ kind: 'exclude', selector: other.selector }));
45
+ }
46
+ filter(options = {}) {
47
+ for (const inner of [options.has, options.hasNot]) {
48
+ if (inner && inner.page !== this.page)
49
+ throw new Error('Filter locators must belong to the same page');
50
+ }
51
+ return this.locator(semanticSelector({ ...options, kind: 'filter', has: options.has?.selector, hasNot: options.hasNot?.selector }));
52
+ }
53
+ nth(index) {
54
+ if (!Number.isInteger(index))
55
+ throw new Error('Locator index must be an integer');
56
+ return this.locator(semanticSelector({ kind: 'nth', index }));
57
+ }
58
+ first() { return this.nth(0); }
59
+ last() { return this.nth(-1); }
60
+ locator(selector, options) {
61
+ const result = new LocatorImpl({
41
62
  page: this.page,
42
63
  selector: chainSelectorForTransport(this.selector, selector),
43
64
  });
65
+ return options ? result.filter(options) : result;
44
66
  }
45
67
  }
package/dist/page.d.ts CHANGED
@@ -1,12 +1,13 @@
1
+ import { WebLocatorBuilders, type LocatorFilterOptions } from "./web-locators.js";
1
2
  import type { AccessibilitySnapshotOptions, ClickResult, CommandOptions, CountResult, ElementResult, FillResult, HighlightOptions, HighlightResult, Locator, NavigateResult, Page, PageInfo, PressOptions, PressResult, RuntimeClient, ScreenshotOptions, ScreenshotResult, TextResult, WaitForSelectorOptions, WaitForSelectorResult } from "./types.js";
2
- export declare class PageImpl implements Page {
3
+ export declare class PageImpl extends WebLocatorBuilders implements Page {
3
4
  #private;
4
5
  constructor(input: PageInfo & {
5
6
  runtime: RuntimeClient;
6
7
  });
7
8
  readonly sessionId: string;
8
9
  readonly browserSessionId: string;
9
- locator(selector: string): Locator;
10
+ locator(selector: string, options?: LocatorFilterOptions): Locator;
10
11
  goto(url: string, options?: CommandOptions): Promise<NavigateResult>;
11
12
  click(selector: string, options?: CommandOptions): Promise<ClickResult>;
12
13
  count(selector: string, options?: CommandOptions): Promise<CountResult>;
package/dist/page.js CHANGED
@@ -1,20 +1,23 @@
1
+ import { WebLocatorBuilders } from "./web-locators.js";
1
2
  import { LocatorImpl } from "./locator.js";
2
3
  import { writeFile } from "node:fs/promises";
3
4
  import { formatActionError } from "./errors.js";
4
5
  import { normalizeSelectorForTransport } from "./selectors.js";
5
6
  import { createPageHandle } from "./runtime.js";
6
- export class PageImpl {
7
+ export class PageImpl extends WebLocatorBuilders {
7
8
  #runtime;
8
9
  #handlePromise = null;
9
10
  constructor(input) {
11
+ super();
10
12
  this.#runtime = input.runtime;
11
13
  this.sessionId = input.sessionId;
12
14
  this.browserSessionId = input.browserSessionId;
13
15
  }
14
16
  sessionId;
15
17
  browserSessionId;
16
- locator(selector) {
17
- return new LocatorImpl({ page: this, selector: normalizeSelectorForTransport(selector) });
18
+ locator(selector, options) {
19
+ const result = new LocatorImpl({ page: this, selector: normalizeSelectorForTransport(selector) });
20
+ return options ? result.filter(options) : result;
18
21
  }
19
22
  async goto(url, options = {}) {
20
23
  const handle = await this.#getHandle();
@@ -306,6 +309,10 @@ export class PageImpl {
306
309
  }
307
310
  }
308
311
  async accessibilitySnapshot(options = {}) {
312
+ const mode = options.mode ?? "default";
313
+ if (!["default", "ai", "autoexpect", "codegen"].includes(mode)) {
314
+ throw new Error("invalid accessibility snapshot mode");
315
+ }
309
316
  const format = options.format ?? "json";
310
317
  if (format !== "json" && format !== "yaml") {
311
318
  throw new Error("accessibility snapshot format must be 'json' or 'yaml'");
@@ -317,6 +324,7 @@ export class PageImpl {
317
324
  contextSessionId: this.sessionId,
318
325
  accessibilitySnapshot: {
319
326
  format,
327
+ mode,
320
328
  retryOptions: options.timeoutMs ? { timeoutMs: options.timeoutMs } : undefined,
321
329
  },
322
330
  });
@@ -1,4 +1,4 @@
1
- export type SelectorFlavor = "css" | "xpath";
1
+ export type SelectorFlavor = "css" | "xpath" | "aw";
2
2
  export declare function parseSelectorForTransport(selector: string): {
3
3
  flavor: SelectorFlavor;
4
4
  body: string;
package/dist/selectors.js CHANGED
@@ -1,4 +1,4 @@
1
- const SELECTOR_PREFIXES = ["xpath=", "xpath:", "css=", "css:"];
1
+ const SELECTOR_PREFIXES = ["aw=", "xpath=", "xpath:", "css=", "css:"];
2
2
  function decodeSelectorBody(body) {
3
3
  const candidate = body.trim();
4
4
  if (candidate.startsWith("\"") && candidate.endsWith("\"")) {
@@ -13,6 +13,8 @@ function decodeSelectorBody(body) {
13
13
  }
14
14
  function parseExplicitSelectorPrefix(selector) {
15
15
  const lowered = selector.toLowerCase();
16
+ if (lowered.startsWith("aw="))
17
+ return { flavor: "aw", prefixLength: 3 };
16
18
  if (lowered.startsWith("xpath=") || lowered.startsWith("xpath:")) {
17
19
  return { flavor: "xpath", prefixLength: 6 };
18
20
  }
package/dist/types.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { WebLocators, LocatorFilterOptions } from "./web-locators.js";
1
2
  import grpc from "@grpc/grpc-js";
2
3
  export { AllwrightError } from "./errors.js";
3
4
  export interface LaunchOptions {
@@ -10,6 +11,7 @@ export interface CommandOptions {
10
11
  }
11
12
  export interface AccessibilitySnapshotOptions extends CommandOptions {
12
13
  format?: "json" | "yaml";
14
+ mode?: "default" | "ai" | "autoexpect" | "codegen";
13
15
  }
14
16
  export interface NavigateResult {
15
17
  url: string;
@@ -107,9 +109,9 @@ export interface Browser extends BrowserInfo {
107
109
  ping(message?: string): Promise<string>;
108
110
  browserInfo(): BrowserInfo;
109
111
  }
110
- export interface Page extends PageInfo {
112
+ export interface Page extends PageInfo, WebLocators {
111
113
  accessibilitySnapshot(options?: AccessibilitySnapshotOptions): Promise<string>;
112
- locator(selector: string): Locator;
114
+ locator(selector: string, options?: LocatorFilterOptions): Locator;
113
115
  goto(url: string, options?: CommandOptions): Promise<NavigateResult>;
114
116
  navigate(url: string, options?: CommandOptions): Promise<NavigateResult>;
115
117
  click(selector: string, options?: CommandOptions): Promise<ClickResult>;
@@ -177,7 +179,12 @@ export interface MobileSurfaceNamespace {
177
179
  connect(options?: MobileAndroidConnectOptions): Promise<MobileAndroidDevice>;
178
180
  };
179
181
  }
180
- export interface Locator {
182
+ export interface Locator extends WebLocators {
183
+ not(other: Locator): Locator;
184
+ filter(options?: LocatorFilterOptions): Locator;
185
+ nth(index: number): Locator;
186
+ first(): Locator;
187
+ last(): Locator;
181
188
  readonly page: Page;
182
189
  readonly selector: string;
183
190
  click(options?: CommandOptions): Promise<ClickResult>;
@@ -190,7 +197,7 @@ export interface Locator {
190
197
  textContent(options?: CommandOptions): Promise<TextResult>;
191
198
  innerText(options?: CommandOptions): Promise<TextResult>;
192
199
  waitFor(options?: WaitForSelectorOptions): Promise<WaitForSelectorResult>;
193
- locator(selector: string): Locator;
200
+ locator(selector: string, options?: LocatorFilterOptions): Locator;
194
201
  }
195
202
  export interface AllwrightConfig {
196
203
  schemaVersion?: 1;
@@ -604,6 +611,7 @@ export interface AccessibilitySnapshotRequest {
604
611
  contextSessionId: string;
605
612
  accessibilitySnapshot: {
606
613
  format: string;
614
+ mode: string;
607
615
  retryOptions?: {
608
616
  timeoutMs?: number;
609
617
  };
@@ -0,0 +1,43 @@
1
+ import type { Locator } from './types.js';
2
+ export type TextMatcher = string | RegExp;
3
+ export interface TextOptions {
4
+ exact?: boolean;
5
+ }
6
+ export interface RoleOptions extends TextOptions {
7
+ name?: TextMatcher;
8
+ checked?: boolean;
9
+ disabled?: boolean;
10
+ expanded?: boolean;
11
+ includeHidden?: boolean;
12
+ level?: number;
13
+ pressed?: boolean;
14
+ selected?: boolean;
15
+ }
16
+ export interface LocatorFilterOptions {
17
+ has?: Locator;
18
+ hasNot?: Locator;
19
+ hasText?: TextMatcher;
20
+ hasNotText?: TextMatcher;
21
+ visible?: boolean;
22
+ }
23
+ export interface WebLocators {
24
+ getByRole(role: string, options?: RoleOptions): Locator;
25
+ getByText(text: TextMatcher, options?: TextOptions): Locator;
26
+ getByLabel(text: TextMatcher, options?: TextOptions): Locator;
27
+ getByPlaceholder(text: TextMatcher, options?: TextOptions): Locator;
28
+ getByAltText(text: TextMatcher, options?: TextOptions): Locator;
29
+ getByTitle(text: TextMatcher, options?: TextOptions): Locator;
30
+ getByTestId(text: TextMatcher): Locator;
31
+ }
32
+ export declare function semanticSelector(spec: Record<string, unknown>): string;
33
+ /** Locator construction only; DOM matching belongs to the web plugin. */
34
+ export declare abstract class WebLocatorBuilders implements WebLocators {
35
+ abstract locator(selector: string, options?: LocatorFilterOptions): Locator;
36
+ getByRole(role: string, options?: RoleOptions): Locator;
37
+ getByText(text: TextMatcher, options?: TextOptions): Locator;
38
+ getByLabel(text: TextMatcher, options?: TextOptions): Locator;
39
+ getByPlaceholder(text: TextMatcher, options?: TextOptions): Locator;
40
+ getByAltText(text: TextMatcher, options?: TextOptions): Locator;
41
+ getByTitle(text: TextMatcher, options?: TextOptions): Locator;
42
+ getByTestId(text: TextMatcher): Locator;
43
+ }
@@ -0,0 +1,18 @@
1
+ export function semanticSelector(spec) {
2
+ return `aw=${JSON.stringify(JSON.stringify(spec, (_key, value) => value instanceof RegExp ? { regex: value.source, flags: value.flags } : value))}`;
3
+ }
4
+ /** Locator construction only; DOM matching belongs to the web plugin. */
5
+ export class WebLocatorBuilders {
6
+ getByRole(role, options = {}) {
7
+ if (options.level !== undefined && (!Number.isInteger(options.level) || options.level < 1)) {
8
+ throw new Error('Role level must be a positive integer');
9
+ }
10
+ return this.locator(semanticSelector({ ...options, kind: 'role', role }));
11
+ }
12
+ getByText(text, options = {}) { return this.locator(semanticSelector({ ...options, kind: 'text', text })); }
13
+ getByLabel(text, options = {}) { return this.locator(semanticSelector({ ...options, kind: 'label', text })); }
14
+ getByPlaceholder(text, options = {}) { return this.locator(semanticSelector({ ...options, kind: 'placeholder', text })); }
15
+ getByAltText(text, options = {}) { return this.locator(semanticSelector({ ...options, kind: 'altText', text })); }
16
+ getByTitle(text, options = {}) { return this.locator(semanticSelector({ ...options, kind: 'title', text })); }
17
+ getByTestId(text) { return this.locator(semanticSelector({ kind: 'testId', text })); }
18
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@allwright.dev/core",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "High-level TypeScript client for the allwright automation engine.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -42,6 +42,9 @@ message ChromeLaunchedEvent {
42
42
 
43
43
  // Empty format defaults to JSON. Accepted values are "json" and "yaml".
44
44
  message AccessibilitySnapshotCommand {
45
+ // Empty mode defaults to default. AI injects queryable aria-ref attributes.
46
+ // Supported: default, ai, autoexpect, codegen.
47
+ string mode = 3;
45
48
  string format = 1;
46
49
  optional CommandRetryOptions retry_options = 2;
47
50
  }