@sun-asterisk/sungen 3.2.30 → 3.2.32
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/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/audit.js +3 -1
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/capability.d.ts.map +1 -1
- package/dist/cli/commands/capability.js +11 -0
- package/dist/cli/commands/capability.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +2 -0
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/setup-mobile-env.d.ts +15 -0
- package/dist/cli/commands/setup-mobile-env.d.ts.map +1 -0
- package/dist/cli/commands/setup-mobile-env.js +65 -0
- package/dist/cli/commands/setup-mobile-env.js.map +1 -0
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/all-contain-assertion.hbs +1 -2
- package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/all-contain-element.hbs +8 -5
- package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/count-assertion.hbs +5 -1
- package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/disabled-with-filter-assertion.hbs +1 -1
- package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/disabled-with-role-variable-assertion.hbs +1 -1
- package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/hidden-with-filter-assertion.hbs +1 -1
- package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/hidden-with-role-variable-assertion.hbs +1 -1
- package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/list-item-count-assertion.hbs +5 -2
- package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/state-with-filter-assertion.hbs +1 -1
- package/dist/generators/test-generator/adapters/appium/templates/steps/assertions/visible-filtered-assertion.hbs +1 -1
- package/dist/generators/test-generator/adapters/appium/templates/steps/partials/await-elements.hbs +12 -0
- package/dist/generators/test-generator/adapters/appium/templates/test-file.hbs +26 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/capture-variable.hbs +7 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/row-scoped-column-assertion.hbs +23 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator-base.hbs +4 -4
- package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator-strategies/default.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator-strategies/id.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs +4 -4
- package/dist/generators/test-generator/adapters/playwright/templates/steps/partials/url-assertion.hbs +13 -2
- package/dist/generators/test-generator/adapters/playwright/templates/test-file.hbs +14 -0
- package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
- package/dist/generators/test-generator/code-generator.js +56 -13
- package/dist/generators/test-generator/code-generator.js.map +1 -1
- package/dist/generators/test-generator/diagnostics.d.ts +39 -2
- package/dist/generators/test-generator/diagnostics.d.ts.map +1 -1
- package/dist/generators/test-generator/diagnostics.js +38 -1
- package/dist/generators/test-generator/diagnostics.js.map +1 -1
- package/dist/generators/test-generator/patterns/index.d.ts +1 -1
- package/dist/generators/test-generator/patterns/index.js +1 -1
- package/dist/generators/test-generator/step-mapper.d.ts +35 -0
- package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
- package/dist/generators/test-generator/step-mapper.js +103 -4
- package/dist/generators/test-generator/step-mapper.js.map +1 -1
- package/dist/generators/test-generator/template-engine.d.ts.map +1 -1
- package/dist/generators/test-generator/template-engine.js +18 -0
- package/dist/generators/test-generator/template-engine.js.map +1 -1
- package/dist/generators/test-generator/utils/selector-resolver.d.ts +47 -0
- package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
- package/dist/generators/test-generator/utils/selector-resolver.js +17 -3
- package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
- package/dist/harness/audit.d.ts.map +1 -1
- package/dist/harness/audit.js +23 -4
- package/dist/harness/audit.js.map +1 -1
- package/dist/harness/next-step.d.ts.map +1 -1
- package/dist/harness/next-step.js +2 -1
- package/dist/harness/next-step.js.map +1 -1
- package/dist/harness/parse.d.ts.map +1 -1
- package/dist/harness/parse.js +42 -7
- package/dist/harness/parse.js.map +1 -1
- package/dist/harness/spec-branches.d.ts +7 -2
- package/dist/harness/spec-branches.d.ts.map +1 -1
- package/dist/harness/spec-branches.js +62 -11
- package/dist/harness/spec-branches.js.map +1 -1
- package/dist/harness/spec-coverage.d.ts +16 -0
- package/dist/harness/spec-coverage.d.ts.map +1 -1
- package/dist/harness/spec-coverage.js +119 -10
- package/dist/harness/spec-coverage.js.map +1 -1
- package/dist/orchestrator/appium-environment-setup.d.ts +24 -0
- package/dist/orchestrator/appium-environment-setup.d.ts.map +1 -0
- package/dist/orchestrator/appium-environment-setup.js +157 -0
- package/dist/orchestrator/appium-environment-setup.js.map +1 -0
- package/dist/orchestrator/mobile-runtime-scaffolder.d.ts +2 -0
- package/dist/orchestrator/mobile-runtime-scaffolder.d.ts.map +1 -1
- package/dist/orchestrator/mobile-runtime-scaffolder.js.map +1 -1
- package/dist/orchestrator/project-initializer.d.ts +1 -0
- package/dist/orchestrator/project-initializer.d.ts.map +1 -1
- package/dist/orchestrator/project-initializer.js +14 -0
- package/dist/orchestrator/project-initializer.js.map +1 -1
- package/dist/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +5 -1
- package/dist/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +55 -2
- package/dist/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +20 -5
- package/dist/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md +3 -3
- package/dist/orchestrator/templates/appium-environment/README.md +83 -0
- package/dist/orchestrator/templates/appium-environment/scripts/common/install-appium.ps1 +44 -0
- package/dist/orchestrator/templates/appium-environment/scripts/common/install-appium.sh +50 -0
- package/dist/orchestrator/templates/appium-environment/scripts/common/lib.ps1 +108 -0
- package/dist/orchestrator/templates/appium-environment/scripts/common/lib.sh +141 -0
- package/dist/orchestrator/templates/appium-environment/scripts/common/verify-appium.ps1 +39 -0
- package/dist/orchestrator/templates/appium-environment/scripts/common/verify-appium.sh +43 -0
- package/dist/orchestrator/templates/appium-environment/scripts/common/verify-node.ps1 +13 -0
- package/dist/orchestrator/templates/appium-environment/scripts/common/verify-node.sh +16 -0
- package/dist/orchestrator/templates/appium-environment/scripts/macos/install-android.sh +110 -0
- package/dist/orchestrator/templates/appium-environment/scripts/macos/install-ios.sh +32 -0
- package/dist/orchestrator/templates/appium-environment/scripts/macos/verify-android.sh +32 -0
- package/dist/orchestrator/templates/appium-environment/scripts/macos/verify-ios.sh +15 -0
- package/dist/orchestrator/templates/appium-environment/scripts/windows/install-android.ps1 +153 -0
- package/dist/orchestrator/templates/appium-environment/scripts/windows/verify-android.ps1 +26 -0
- package/dist/orchestrator/templates/appium-environment/setup.ps1 +58 -0
- package/dist/orchestrator/templates/appium-environment/setup.sh +88 -0
- package/dist/orchestrator/templates/specs-checked-state.d.ts +1 -1
- package/dist/orchestrator/templates/specs-checked-state.d.ts.map +1 -1
- package/dist/orchestrator/templates/specs-checked-state.js +26 -3
- package/dist/orchestrator/templates/specs-checked-state.js.map +1 -1
- package/dist/orchestrator/templates/specs-checked-state.ts +31 -6
- package/dist/orchestrator/templates/specs-mock.d.ts +2 -1
- package/dist/orchestrator/templates/specs-mock.d.ts.map +1 -1
- package/dist/orchestrator/templates/specs-mock.js +10 -3
- package/dist/orchestrator/templates/specs-mock.js.map +1 -1
- package/dist/orchestrator/templates/specs-mock.ts +12 -4
- package/package.json +3 -3
- package/src/cli/commands/audit.ts +2 -1
- package/src/cli/commands/capability.ts +12 -1
- package/src/cli/commands/init.ts +3 -0
- package/src/cli/commands/setup-mobile-env.ts +64 -0
- package/src/cli/index.ts +2 -0
- package/src/generators/test-generator/adapters/appium/templates/steps/assertions/all-contain-assertion.hbs +1 -2
- package/src/generators/test-generator/adapters/appium/templates/steps/assertions/all-contain-element.hbs +8 -5
- package/src/generators/test-generator/adapters/appium/templates/steps/assertions/count-assertion.hbs +5 -1
- package/src/generators/test-generator/adapters/appium/templates/steps/assertions/disabled-with-filter-assertion.hbs +1 -1
- package/src/generators/test-generator/adapters/appium/templates/steps/assertions/disabled-with-role-variable-assertion.hbs +1 -1
- package/src/generators/test-generator/adapters/appium/templates/steps/assertions/hidden-with-filter-assertion.hbs +1 -1
- package/src/generators/test-generator/adapters/appium/templates/steps/assertions/hidden-with-role-variable-assertion.hbs +1 -1
- package/src/generators/test-generator/adapters/appium/templates/steps/assertions/list-item-count-assertion.hbs +5 -2
- package/src/generators/test-generator/adapters/appium/templates/steps/assertions/state-with-filter-assertion.hbs +1 -1
- package/src/generators/test-generator/adapters/appium/templates/steps/assertions/visible-filtered-assertion.hbs +1 -1
- package/src/generators/test-generator/adapters/appium/templates/steps/partials/await-elements.hbs +12 -0
- package/src/generators/test-generator/adapters/appium/templates/test-file.hbs +26 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/capture-variable.hbs +7 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/row-scoped-column-assertion.hbs +23 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator-base.hbs +4 -4
- package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator-strategies/default.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator-strategies/id.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/partials/locator.hbs +4 -4
- package/src/generators/test-generator/adapters/playwright/templates/steps/partials/url-assertion.hbs +13 -2
- package/src/generators/test-generator/adapters/playwright/templates/test-file.hbs +14 -0
- package/src/generators/test-generator/code-generator.ts +66 -17
- package/src/generators/test-generator/diagnostics.ts +39 -2
- package/src/generators/test-generator/patterns/index.ts +1 -1
- package/src/generators/test-generator/step-mapper.ts +106 -5
- package/src/generators/test-generator/template-engine.ts +18 -0
- package/src/generators/test-generator/utils/selector-resolver.ts +18 -3
- package/src/harness/audit.ts +24 -5
- package/src/harness/next-step.ts +2 -1
- package/src/harness/parse.ts +42 -7
- package/src/harness/spec-branches.ts +67 -12
- package/src/harness/spec-coverage.ts +121 -11
- package/src/orchestrator/appium-environment-setup.ts +127 -0
- package/src/orchestrator/mobile-runtime-scaffolder.ts +2 -0
- package/src/orchestrator/project-initializer.ts +15 -1
- package/src/orchestrator/templates/ai-src/skills/sungen-error-mapping/SKILL.md +5 -1
- package/src/orchestrator/templates/ai-src/skills/sungen-gherkin-syntax/SKILL.md +55 -2
- package/src/orchestrator/templates/ai-src/skills/sungen-tc-generation/SKILL.md +20 -5
- package/src/orchestrator/templates/ai-src/skills/sungen-tc-review/SKILL.md +3 -3
- package/src/orchestrator/templates/appium-environment/README.md +83 -0
- package/src/orchestrator/templates/appium-environment/scripts/common/install-appium.ps1 +44 -0
- package/src/orchestrator/templates/appium-environment/scripts/common/install-appium.sh +50 -0
- package/src/orchestrator/templates/appium-environment/scripts/common/lib.ps1 +108 -0
- package/src/orchestrator/templates/appium-environment/scripts/common/lib.sh +141 -0
- package/src/orchestrator/templates/appium-environment/scripts/common/verify-appium.ps1 +39 -0
- package/src/orchestrator/templates/appium-environment/scripts/common/verify-appium.sh +43 -0
- package/src/orchestrator/templates/appium-environment/scripts/common/verify-node.ps1 +13 -0
- package/src/orchestrator/templates/appium-environment/scripts/common/verify-node.sh +16 -0
- package/src/orchestrator/templates/appium-environment/scripts/macos/install-android.sh +110 -0
- package/src/orchestrator/templates/appium-environment/scripts/macos/install-ios.sh +32 -0
- package/src/orchestrator/templates/appium-environment/scripts/macos/verify-android.sh +32 -0
- package/src/orchestrator/templates/appium-environment/scripts/macos/verify-ios.sh +15 -0
- package/src/orchestrator/templates/appium-environment/scripts/windows/install-android.ps1 +153 -0
- package/src/orchestrator/templates/appium-environment/scripts/windows/verify-android.ps1 +26 -0
- package/src/orchestrator/templates/appium-environment/setup.ps1 +58 -0
- package/src/orchestrator/templates/appium-environment/setup.sh +88 -0
- package/src/orchestrator/templates/specs-checked-state.ts +31 -6
- package/src/orchestrator/templates/specs-mock.ts +12 -4
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# setup.sh — macOS entry point of the sungen Appium environment bundle.
|
|
3
|
+
#
|
|
4
|
+
# ./appium-environment/setup.sh [--check] [--skip-android] [--skip-ios] [--no-profile]
|
|
5
|
+
#
|
|
6
|
+
# Emitted by `sungen init --mobile` / `sungen capability add mobile`, which also run it once.
|
|
7
|
+
# Re-run it any time: every step is check → install → verify and a satisfied step is skipped.
|
|
8
|
+
# --check report what is missing, install nothing (side-effect free)
|
|
9
|
+
# --skip-android skip JDK / Android SDK / uiautomator2
|
|
10
|
+
# --skip-ios skip Xcode CLT / applesimutils / xcuitest
|
|
11
|
+
# --no-profile do not write the ANDROID_HOME / JAVA_HOME / PATH block to your shell profile
|
|
12
|
+
# Exit: 0 ready (or only warnings) · 1 something failed · 2 unsupported OS / bad flag
|
|
13
|
+
set -u
|
|
14
|
+
|
|
15
|
+
BUNDLE_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
16
|
+
PROJECT_DIR=$(cd "$BUNDLE_DIR/.." && pwd)
|
|
17
|
+
export PROJECT_DIR
|
|
18
|
+
. "$BUNDLE_DIR/scripts/common/lib.sh"
|
|
19
|
+
|
|
20
|
+
usage() { sed -n '4,13p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'; }
|
|
21
|
+
|
|
22
|
+
for arg in "$@"; do
|
|
23
|
+
case "$arg" in
|
|
24
|
+
--check) SUNGEN_ENV_CHECK_ONLY=1 ;;
|
|
25
|
+
--skip-android) SUNGEN_ENV_SKIP_ANDROID=1 ;;
|
|
26
|
+
--skip-ios) SUNGEN_ENV_SKIP_IOS=1 ;;
|
|
27
|
+
--no-profile) SUNGEN_ENV_NO_PROFILE=1 ;;
|
|
28
|
+
-h|--help) usage; exit 0 ;;
|
|
29
|
+
*) printf 'unknown flag: %s\n\n' "$arg" >&2; usage >&2; exit 2 ;;
|
|
30
|
+
esac
|
|
31
|
+
done
|
|
32
|
+
|
|
33
|
+
case "$(uname -s)" in
|
|
34
|
+
Darwin) ;;
|
|
35
|
+
Linux)
|
|
36
|
+
printf 'ℹ Linux detected — this bundle provisions macOS and Windows.\n'
|
|
37
|
+
printf ' Android on Linux: see README.md → "Manual fallback" (JDK + Android SDK via your package manager,\n'
|
|
38
|
+
printf ' then `sungen capability add mobile` for the project-local Appium + uiautomator2).\n'
|
|
39
|
+
exit 0 ;;
|
|
40
|
+
*) printf '✗ unsupported OS: %s (macOS: setup.sh · Windows: setup.ps1)\n' "$(uname -s)" >&2; exit 2 ;;
|
|
41
|
+
esac
|
|
42
|
+
|
|
43
|
+
cd "$PROJECT_DIR"
|
|
44
|
+
if [ "$SUNGEN_ENV_CHECK_ONLY" = 1 ]; then section "sungen · Appium environment — check only (macOS)"
|
|
45
|
+
else section "sungen · Appium environment setup (macOS)"; fi
|
|
46
|
+
printf '%sproject: %s%s\n' "$C_DIM" "$PROJECT_DIR" "$C_RESET"
|
|
47
|
+
|
|
48
|
+
# ── 1/5 prerequisites ──────────────────────────────────────────────────────────────────────────
|
|
49
|
+
section "1/5 Prerequisites"
|
|
50
|
+
. "$BUNDLE_DIR/scripts/common/verify-node.sh"
|
|
51
|
+
|
|
52
|
+
brew_check() { have brew && printf 'brew at %s' "$(command -v brew)"; }
|
|
53
|
+
brew_install() {
|
|
54
|
+
NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" || return 1
|
|
55
|
+
# The installer does not touch the running shell — pick brew up for the rest of this run.
|
|
56
|
+
if [ -x /opt/homebrew/bin/brew ]; then eval "$(/opt/homebrew/bin/brew shellenv)"
|
|
57
|
+
elif [ -x /usr/local/bin/brew ]; then eval "$(/usr/local/bin/brew shellenv)"; fi
|
|
58
|
+
}
|
|
59
|
+
brew_verify() { brew_check || { printf 'Homebrew not found after install — https://brew.sh, then re-run'; return 1; }; }
|
|
60
|
+
run_step "Homebrew" brew_check brew_install brew_verify
|
|
61
|
+
|
|
62
|
+
# ── 2/5 Android ────────────────────────────────────────────────────────────────────────────────
|
|
63
|
+
if [ "$SUNGEN_ENV_SKIP_ANDROID" != 1 ]; then
|
|
64
|
+
section "2/5 Android (JDK, SDK, adb, emulator)"
|
|
65
|
+
. "$BUNDLE_DIR/scripts/macos/install-android.sh"
|
|
66
|
+
else
|
|
67
|
+
section "2/5 Android"; log_skip "Android toolchain" "--skip-android"
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
# ── 3/5 iOS ────────────────────────────────────────────────────────────────────────────────────
|
|
71
|
+
if [ "$SUNGEN_ENV_SKIP_IOS" != 1 ]; then
|
|
72
|
+
section "3/5 iOS (Xcode, applesimutils)"
|
|
73
|
+
. "$BUNDLE_DIR/scripts/macos/install-ios.sh"
|
|
74
|
+
else
|
|
75
|
+
section "3/5 iOS"; log_skip "iOS toolchain" "--skip-ios"
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
# ── 4/5 Appium ─────────────────────────────────────────────────────────────────────────────────
|
|
79
|
+
section "4/5 Appium (project-local) + platform drivers"
|
|
80
|
+
. "$BUNDLE_DIR/scripts/common/install-appium.sh"
|
|
81
|
+
|
|
82
|
+
# ── 5/5 health ─────────────────────────────────────────────────────────────────────────────────
|
|
83
|
+
section "5/5 Health check"
|
|
84
|
+
[ "$SUNGEN_ENV_SKIP_ANDROID" != 1 ] && . "$BUNDLE_DIR/scripts/macos/verify-android.sh"
|
|
85
|
+
[ "$SUNGEN_ENV_SKIP_IOS" != 1 ] && . "$BUNDLE_DIR/scripts/macos/verify-ios.sh"
|
|
86
|
+
. "$BUNDLE_DIR/scripts/common/verify-appium.sh"
|
|
87
|
+
|
|
88
|
+
print_summary
|
|
@@ -38,7 +38,7 @@ const POLL_INTERVAL_MS = 100;
|
|
|
38
38
|
export interface DeclaredSignal { class?: string; attribute?: string }
|
|
39
39
|
|
|
40
40
|
/** Where the control publishes its on/off state — decided in the page, from the real element. */
|
|
41
|
-
export type StateSource = 'native' | 'aria-pressed' | 'aria-checked' | 'class' | 'attribute' | 'none';
|
|
41
|
+
export type StateSource = 'native' | 'aria-pressed' | 'aria-checked' | 'aria-selected' | 'aria-current' | 'class' | 'attribute' | 'none';
|
|
42
42
|
export interface ControlProbe {
|
|
43
43
|
source: StateSource;
|
|
44
44
|
/** Current state, already normalised. Meaningless when `source` is 'native' (Playwright reads it). */
|
|
@@ -110,6 +110,24 @@ export function probeControl(node: unknown, declared?: DeclaredSignal): ControlP
|
|
|
110
110
|
}
|
|
111
111
|
// Role claims checkable but nothing is published — let Playwright raise its own, precise error.
|
|
112
112
|
if (ariaCheckableRole) return { source: 'native', on: false, buttonLike };
|
|
113
|
+
// `is selected` on a tab, an option, a chip or a nav item. These publish `aria-selected` or
|
|
114
|
+
// `aria-current`, which nothing above reads: the probe fell straight through to 'none' and the
|
|
115
|
+
// step failed saying the control has no on/off state to set, on a control that publishes one in
|
|
116
|
+
// the standard place. Read here rather than in the templates so a suite already generated in the
|
|
117
|
+
// field picks the fix up without regenerating — the same reasoning the URL predicate is a runtime
|
|
118
|
+
// helper for.
|
|
119
|
+
//
|
|
120
|
+
// `aria-current` is not a boolean: the spec allows 'page', 'step', 'location', 'date', 'time' and
|
|
121
|
+
// 'true', and only the literal 'false' (or the attribute's absence) means off. Read that way
|
|
122
|
+
// round, so `aria-current="page"` on the active nav item reads as ON rather than as a stray
|
|
123
|
+
// non-'true' string.
|
|
124
|
+
if (el.hasAttribute('aria-selected')) {
|
|
125
|
+
return { source: 'aria-selected', on: String(el.getAttribute('aria-selected') ?? '').trim().toLowerCase() === 'true', buttonLike };
|
|
126
|
+
}
|
|
127
|
+
if (el.hasAttribute('aria-current')) {
|
|
128
|
+
const raw = String(el.getAttribute('aria-current') ?? '').trim().toLowerCase();
|
|
129
|
+
return { source: 'aria-current', on: raw !== '' && raw !== 'false', buttonLike };
|
|
130
|
+
}
|
|
113
131
|
return { source: 'none', on: false, buttonLike };
|
|
114
132
|
}
|
|
115
133
|
|
|
@@ -132,11 +150,18 @@ const sleep = (ms: number): Promise<void> => new Promise((r) => setTimeout(r, ms
|
|
|
132
150
|
*/
|
|
133
151
|
const left = (deadline: number): number => Math.max(250, deadline - Date.now());
|
|
134
152
|
|
|
153
|
+
/** The sources that name an ATTRIBUTE the live state can be re-read from. */
|
|
154
|
+
type AttributeSource = 'aria-pressed' | 'aria-checked' | 'aria-selected' | 'aria-current';
|
|
155
|
+
|
|
135
156
|
/** Read the live state. A REMOVED attribute means off: `aria-pressed={on || undefined}` is a common
|
|
136
157
|
* React/Vue idiom, so requiring a literal "false" would fail a control that is correctly off. */
|
|
137
|
-
async function readOn(target: Locator, attr:
|
|
138
|
-
const raw = await target.getAttribute(attr, { timeout: left(deadline) });
|
|
139
|
-
|
|
158
|
+
async function readOn(target: Locator, attr: AttributeSource, deadline: number): Promise<boolean> {
|
|
159
|
+
const raw = String(await target.getAttribute(attr, { timeout: left(deadline) }) ?? '').trim().toLowerCase();
|
|
160
|
+
// `aria-current` is the one non-boolean of the four: the spec allows 'page', 'step', 'location',
|
|
161
|
+
// 'date', 'time' and 'true', so only the literal 'false' (or absence) means off. Read the other
|
|
162
|
+
// way round it would report the active nav item as OFF.
|
|
163
|
+
if (attr === 'aria-current') return raw !== '' && raw !== 'false';
|
|
164
|
+
return raw === 'true';
|
|
140
165
|
}
|
|
141
166
|
|
|
142
167
|
/**
|
|
@@ -238,12 +263,12 @@ export async function setCheckedState(
|
|
|
238
263
|
// Not pressable and publishes nothing — there is no reading of this that makes the step meaningful.
|
|
239
264
|
throw new Error(
|
|
240
265
|
`Cannot ${want ? 'check' : 'uncheck'} [${label}] — it is not a checkbox/radio/switch, is not a `
|
|
241
|
-
+ `button, and publishes no aria-pressed/aria-checked, so it has no on/off state to set. Point the `
|
|
266
|
+
+ `button, and publishes no aria-pressed/aria-checked/aria-selected/aria-current, so it has no on/off state to set. Point the `
|
|
242
267
|
+ `selector at the control itself, or give it a real ARIA toggle role.`,
|
|
243
268
|
);
|
|
244
269
|
}
|
|
245
270
|
|
|
246
|
-
const attr = probe.source;
|
|
271
|
+
const attr: AttributeSource = probe.source as AttributeSource;
|
|
247
272
|
// Already in the requested state → nothing to do. This is the idempotence `check` promises.
|
|
248
273
|
if (probe.on === want) return;
|
|
249
274
|
await target.click({ timeout });
|
|
@@ -25,7 +25,8 @@ export interface MockConfig {
|
|
|
25
25
|
name: string;
|
|
26
26
|
method: string; // HTTP verb or '*'
|
|
27
27
|
url: string; // page.route glob, or 're:<pattern>' for a regex
|
|
28
|
-
status
|
|
28
|
+
status?: number; // the server ANSWERED — absent exactly when `abort` is set
|
|
29
|
+
abort?: string; // the request NEVER ARRIVED — a route.abort() errorCode
|
|
29
30
|
headers?: Record<string, string>;
|
|
30
31
|
body?: string; // pre-serialized by the compiler (JSON string)
|
|
31
32
|
delay_ms?: number;
|
|
@@ -104,9 +105,16 @@ class MockRouter {
|
|
|
104
105
|
if (cfg.method !== '*' && route.request().method() !== cfg.method) return route.fallback();
|
|
105
106
|
st.counts.set(cfg.name, (st.counts.get(cfg.name) ?? 0) + 1);
|
|
106
107
|
if (cfg.delay_ms) await new Promise((r) => setTimeout(r, cfg.delay_ms));
|
|
107
|
-
// A delayed
|
|
108
|
-
// not surface as an unhandled rejection from inside a route handler.
|
|
109
|
-
|
|
108
|
+
// A delayed response can race a page close / reset at teardown — that race must
|
|
109
|
+
// not surface as an unhandled rejection from inside a route handler. It wraps BOTH
|
|
110
|
+
// outcomes: an abort races teardown exactly like a fulfill does.
|
|
111
|
+
try {
|
|
112
|
+
// `abort` is the request that never reaches the server; `status` is the one the
|
|
113
|
+
// server answered. The catalog refuses an entry carrying both, so this is a real
|
|
114
|
+
// either/or, not a precedence rule (#676).
|
|
115
|
+
if (cfg.abort) await route.abort(cfg.abort);
|
|
116
|
+
else await route.fulfill({ status: cfg.status, headers: cfg.headers, body: cfg.body });
|
|
117
|
+
} catch { /* page closing */ }
|
|
110
118
|
};
|
|
111
119
|
await page.route(pattern, handler);
|
|
112
120
|
st.routes.push({ pattern, handler });
|