nativeproof 0.8.0 → 0.10.0

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/CHANGELOG.md CHANGED
@@ -4,6 +4,28 @@ All notable changes to NativeProof are documented here. The format follows
4
4
  [Keep a Changelog](https://keepachangelog.com/) and the project adheres to
5
5
  [Semantic Versioning](https://semver.org/).
6
6
 
7
+ ## 0.10.0
8
+
9
+ Element enabled-state assertions.
10
+
11
+ **Added**
12
+
13
+ - **`Locator.isEnabled()` / `isDisabled()` and `expect(locator).toBeEnabled()` / `toBeDisabled()`** —
14
+ read the matched element's `enabled` attribute (present and not `enabled="false"` is enabled, matching
15
+ Playwright's default-enabled semantics). Auto-waiting, `.not` inverts. For asserting a button/control
16
+ flips between enabled and disabled as a form validates.
17
+
18
+ ## 0.9.0
19
+
20
+ Regex frame matching — `expect(mock)` matches traffic by pattern.
21
+
22
+ **Added**
23
+
24
+ - **`toHaveSent` / `toHaveReceived` (and `FrameMatch`) accept a `RegExp`** for `path`, `type`, and any
25
+ payload field — `expect(mock).toHaveSent({ path: /\/users/, type: "request" })` matches a
26
+ query-suffixed or otherwise variable path, mirroring regex selectors on the locator side. A string
27
+ stays an exact match (deep equality for payload objects); a RegExp tests the actual string value.
28
+
7
29
  ## 0.8.0
8
30
 
9
31
  Relative locators — `Locator.near` scopes to the match nearest an anchor.
package/README.md CHANGED
@@ -489,6 +489,7 @@ await expect(member.spinner).not.toBeVisible({ timeout: 5_000 });
489
489
  - `toShow(text, opts?)` — the selector is present **and** `text` appears in the source.
490
490
  - `toHaveText(text, opts?)` — the matched node's **own** text contains / matches `text`.
491
491
  - `toBeChecked(opts?)` — the matched checkbox / switch is checked (`checked="true"`).
492
+ - `toBeEnabled(opts?)` / `toBeDisabled(opts?)` — the matched element's `enabled` state.
492
493
  - `toHaveCount(n, opts?)` — exactly `n` elements match the selector.
493
494
  - `opts` is `{ timeout?, interval? }` (ms).
494
495
 
@@ -555,7 +556,8 @@ test.describe("chat room", "member", () => {
555
556
  - `mock.route(path).reject({ code })` — fail it (HTTP status, or WebSocket close code 3000–4999).
556
557
  - `mock.route(path).abort()` — drop the connect/request entirely.
557
558
  - `expect(mock).toHaveSent(match)` / `toHaveReceived(match)` — `match` is a partial frame:
558
- `path` / `type` plus any payload fields.
559
+ `path` / `type` plus any payload fields. Each field is a string (exact / deep-equal) **or a `RegExp`**
560
+ (`toHaveSent({ path: /\/users/, type: "request" })`) to match a query-suffixed or variable path.
559
561
 
560
562
  **Frame types** — real protocol messages keep their own `type` (a WS JSON message's `type`); the
561
563
  server also synthesises types for primitives so you can assert on them:
package/dist/expect.d.ts CHANGED
@@ -16,6 +16,10 @@ export interface LocatorAssertions {
16
16
  toHaveText(text: string | RegExp, options?: WaitOptions): Promise<void>;
17
17
  /** The matched checkbox/switch is checked (`checked="true"`). */
18
18
  toBeChecked(options?: WaitOptions): Promise<void>;
19
+ /** The matched element is enabled (present and not `enabled="false"`). */
20
+ toBeEnabled(options?: WaitOptions): Promise<void>;
21
+ /** The matched element is present and `enabled="false"`. */
22
+ toBeDisabled(options?: WaitOptions): Promise<void>;
19
23
  /** Exactly `count` elements match the selector. */
20
24
  toHaveCount(count: number, options?: WaitOptions): Promise<void>;
21
25
  }
package/dist/expect.js CHANGED
@@ -28,6 +28,12 @@ class LocatorExpectation {
28
28
  toBeChecked(options = {}) {
29
29
  return this.check(() => this.locator.isChecked(), "be checked", options);
30
30
  }
31
+ toBeEnabled(options = {}) {
32
+ return this.check(() => this.locator.isEnabled(), "be enabled", options);
33
+ }
34
+ toBeDisabled(options = {}) {
35
+ return this.check(() => this.locator.isDisabled(), "be disabled", options);
36
+ }
31
37
  toHaveCount(count, options = {}) {
32
38
  return this.check(async () => (await this.locator.count()) === count, `have count ${count}`, options);
33
39
  }
package/dist/locator.d.ts CHANGED
@@ -130,6 +130,10 @@ export declare class Locator {
130
130
  fill(text: string, options?: WaitOptions): Promise<void>;
131
131
  /** True if the matched node is a checked checkbox/switch (`checked="true"`). */
132
132
  isChecked(): Promise<boolean>;
133
+ /** True if the matched node is present and not `enabled="false"` (matches Playwright's default-enabled). */
134
+ isEnabled(): Promise<boolean>;
135
+ /** True if the matched node is present and explicitly `enabled="false"`. */
136
+ isDisabled(): Promise<boolean>;
133
137
  /** Tap to bring a checkbox/switch to checked; a no-op if it already is. */
134
138
  check(options?: WaitOptions): Promise<void>;
135
139
  /** Tap to bring a checkbox/switch to unchecked; a no-op if it already is. */
package/dist/locator.js CHANGED
@@ -212,6 +212,16 @@ export class Locator {
212
212
  const node = this.pick(await this.matchedNodes());
213
213
  return node !== null && /\bchecked="true"/.test(node);
214
214
  }
215
+ /** True if the matched node is present and not `enabled="false"` (matches Playwright's default-enabled). */
216
+ async isEnabled() {
217
+ const node = this.pick(await this.matchedNodes());
218
+ return node !== null && !/\benabled="false"/.test(node);
219
+ }
220
+ /** True if the matched node is present and explicitly `enabled="false"`. */
221
+ async isDisabled() {
222
+ const node = this.pick(await this.matchedNodes());
223
+ return node !== null && /\benabled="false"/.test(node);
224
+ }
215
225
  /** Tap to bring a checkbox/switch to checked; a no-op if it already is. */
216
226
  async check(options = {}) {
217
227
  await this.setChecked(true, options);
package/dist/mock.d.ts CHANGED
@@ -18,8 +18,8 @@ export interface MockFrame {
18
18
  }
19
19
  /** A partial frame to match against: `path` / `type` plus any payload fields. */
20
20
  export interface FrameMatch {
21
- path?: string;
22
- type?: string;
21
+ path?: string | RegExp;
22
+ type?: string | RegExp;
23
23
  [key: string]: unknown;
24
24
  }
25
25
  /** Controls how an intercepted path replies — the Playwright `Route` equivalent. */
package/dist/mock.js CHANGED
@@ -1,23 +1,33 @@
1
1
  import { isDeepStrictEqual } from "node:util";
2
+ /**
3
+ * Match one field of an observed frame against an expected value: a `RegExp` tests the
4
+ * actual string (so paths with query/suffix match — `toHaveSent({ path: /\/users/ })`),
5
+ * anything else is deep structural equality.
6
+ */
7
+ function fieldMatches(actual, expected) {
8
+ if (expected instanceof RegExp)
9
+ return typeof actual === "string" && expected.test(actual);
10
+ return isDeepStrictEqual(actual, expected);
11
+ }
2
12
  /**
3
13
  * True if `frame` satisfies every field of `match`: `path` / `type` at the top level,
4
14
  * every other key against the frame's payload.
5
15
  */
6
16
  export function matchesFrame(frame, match) {
7
- if (match.path !== undefined && frame.path !== match.path)
17
+ if (match.path !== undefined && !fieldMatches(frame.path, match.path))
8
18
  return false;
9
- if (match.type !== undefined && frame.type !== match.type)
19
+ if (match.type !== undefined && !fieldMatches(frame.type, match.type))
10
20
  return false;
11
21
  for (const [key, value] of Object.entries(match)) {
12
22
  if (key === "path" || key === "type")
13
23
  continue;
14
- if (!isDeepStrictEqual(frame.payload?.[key], value))
24
+ if (!fieldMatches(frame.payload?.[key], value))
15
25
  return false;
16
26
  }
17
27
  return true;
18
28
  }
19
29
  export function describeMatch(match) {
20
- return JSON.stringify(match);
30
+ return JSON.stringify(match, (_key, value) => (value instanceof RegExp ? String(value) : value));
21
31
  }
22
32
  /** Single-shot check: does any observed frame match `match` in `direction`? */
23
33
  export async function frameExists(source, direction, match) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nativeproof",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "Native Mobile E2E test framework inspired by Playwright (fixtures, locators, expect, route-style mocking) on Appium/WebdriverIO.",