@sungen/driver-mobile 3.2.24-beta.5 → 3.2.24
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sungen/driver-mobile",
|
|
3
|
-
"version": "3.2.24
|
|
3
|
+
"version": "3.2.24",
|
|
4
4
|
"description": "Sungen mobile platform driver (Appium / WebdriverIO) — gesture vocabulary, mobile selector strategies, viewpoint gate, and the WDIO runner. Plugs into @sun-asterisk/sungen via the capability SPI.",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"author": "eqe team (engineer & quality) — Sun Asterisk",
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@sun-asterisk/sungen": "3.2.24
|
|
16
|
+
"@sun-asterisk/sungen": "3.2.24",
|
|
17
17
|
"@wdio/appium-service": "^9.0.0",
|
|
18
18
|
"@wdio/cli": "^9.0.0",
|
|
19
19
|
"@wdio/local-runner": "^9.0.0",
|
package/src/index.ts
CHANGED
|
@@ -37,6 +37,10 @@ import type {
|
|
|
37
37
|
GenerationUnit,
|
|
38
38
|
} from '@sun-asterisk/sungen';
|
|
39
39
|
import { gesturePatterns } from './patterns/gesture-patterns';
|
|
40
|
+
import { lifecyclePatterns } from './patterns/lifecycle-patterns';
|
|
41
|
+
import { devicePatterns } from './patterns/device-patterns';
|
|
42
|
+
import { timingPatterns } from './patterns/timing-patterns';
|
|
43
|
+
import { logPatterns } from './patterns/log-patterns';
|
|
40
44
|
|
|
41
45
|
/** Surfaces universal-viewpoint theme gaps (low-priority reminder; does not move the score). */
|
|
42
46
|
const mobileViewpointGateSensor: Sensor<GateInput> = {
|
|
@@ -71,6 +75,10 @@ export function register(registry: CapabilityRegistry): void {
|
|
|
71
75
|
annotations: [],
|
|
72
76
|
patterns: [
|
|
73
77
|
...gesturePatterns, // MOB-3: tap/double-tap + swipe/long-press/pinch/pull-to-refresh/rotate/… → appium templates
|
|
78
|
+
...lifecyclePatterns, // #600: restart/reinstall the app (persistence oracles)
|
|
79
|
+
...devicePatterns, // #600: airplane/wifi/data + location-services toggles (Android-only at runtime)
|
|
80
|
+
...timingPatterns, // #600: disappears-within / still-visible-after windows
|
|
81
|
+
...logPatterns, // #603: device-log oracle (silent failures / analytics)
|
|
74
82
|
],
|
|
75
83
|
discovery: mobileDiscovery,
|
|
76
84
|
contextMapper: mobileContextMapper,
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device-state step patterns — connectivity + location services (issue #600).
|
|
3
|
+
*
|
|
4
|
+
* Offline/airplane behavior and the location-permission matrices pivot on toggling device
|
|
5
|
+
* state mid-scenario. Android-only at runtime (`mobile: setConnectivity`,
|
|
6
|
+
* `toggleLocationServices` — verified against uiautomator2 7.6.2); the templates throw a
|
|
7
|
+
* named error on iOS instead of silently skipping (XCUITest has no such control).
|
|
8
|
+
*/
|
|
9
|
+
import { StepPattern } from '@sun-asterisk/sungen';
|
|
10
|
+
|
|
11
|
+
/** `on|off` from the step text; defaults to `on` only when neither word appears (explicit wins). */
|
|
12
|
+
function wantsOn(text: string): boolean {
|
|
13
|
+
if (/\boff\b/i.test(text)) return false;
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const devicePatterns: StepPattern[] = [
|
|
18
|
+
{
|
|
19
|
+
// `User turn airplane mode on` / `User turns wifi off` / `User turn mobile data off`.
|
|
20
|
+
// Keyed on the device noun + turn/enable/disable so it never collides with UI toggles
|
|
21
|
+
// (`tap [Wifi Switch]` carries a selectorRef and a tap verb).
|
|
22
|
+
name: 'set-connectivity',
|
|
23
|
+
matcher: (step) =>
|
|
24
|
+
/\b(airplane(?:\s+mode)?|wi-?fi|mobile\s+data)\b/i.test(step.text) &&
|
|
25
|
+
/\b(turn(s)?|enable(s)?|disable(s)?|switch(es)?)\b/i.test(step.text) &&
|
|
26
|
+
!step.selectorRef,
|
|
27
|
+
resolver: (step) => {
|
|
28
|
+
const text = step.text;
|
|
29
|
+
const isAirplane = /\bairplane\b/i.test(text);
|
|
30
|
+
const kind = isAirplane ? 'airplane mode' : /\bwi-?fi\b/i.test(text) ? 'wifi' : 'mobile data';
|
|
31
|
+
const kindKey = kind === 'mobile data' ? 'data' : 'wifi'; // non-airplane arg name for mobile: setConnectivity
|
|
32
|
+
const on = /\bdisable(s)?\b/i.test(text) ? false : wantsOn(text);
|
|
33
|
+
return {
|
|
34
|
+
templateName: 'set-connectivity-action',
|
|
35
|
+
data: { kind, kindKey, isAirplane, on },
|
|
36
|
+
comment: `Turn ${kind} ${on ? 'on' : 'off'}`,
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
priority: 16,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
// `User turn device location on|off` / `User disable location services`. Distinct from
|
|
43
|
+
// `set-geolocation` (set/mock/simulate coordinates) — this toggles the SERVICE.
|
|
44
|
+
name: 'location-services',
|
|
45
|
+
matcher: (step) =>
|
|
46
|
+
/\b(device\s+location|location\s+services?)\b/i.test(step.text) &&
|
|
47
|
+
/\b(turn(s)?|enable(s)?|disable(s)?|switch(es)?)\b/i.test(step.text) &&
|
|
48
|
+
!step.selectorRef,
|
|
49
|
+
resolver: (step) => {
|
|
50
|
+
const on = /\bdisable(s)?\b/i.test(step.text) ? false : wantsOn(step.text);
|
|
51
|
+
return { templateName: 'location-services-action', data: { on }, comment: `Turn device location ${on ? 'on' : 'off'}` };
|
|
52
|
+
},
|
|
53
|
+
priority: 16,
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
// `User pass|fail biometric authentication` — simulated biometric input on emulator/simulator
|
|
57
|
+
// (#603). Face wording (`face id`) selects the iOS faceId type; Android is fingerprint-only.
|
|
58
|
+
name: 'biometric-auth',
|
|
59
|
+
matcher: (step) =>
|
|
60
|
+
/\b(biometric|fingerprint|face\s?id|touch\s?id)\b/i.test(step.text) &&
|
|
61
|
+
/\b(pass(es)?|fail(s)?|match(es)?|reject(s)?)\b/i.test(step.text) &&
|
|
62
|
+
!step.selectorRef,
|
|
63
|
+
resolver: (step) => {
|
|
64
|
+
const match = !/\b(fail(s)?|reject(s)?)\b/i.test(step.text);
|
|
65
|
+
const faceId = /\bface\s?id\b/i.test(step.text);
|
|
66
|
+
return { templateName: 'biometric-action', data: { match, faceId }, comment: `${match ? 'Pass' : 'Fail'} biometric authentication` };
|
|
67
|
+
},
|
|
68
|
+
priority: 16,
|
|
69
|
+
},
|
|
70
|
+
];
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App-lifecycle step patterns — restart / reinstall (issue #600).
|
|
3
|
+
*
|
|
4
|
+
* Persistence oracles (pinned card, banner dismiss, tooltip show-once, recent-services
|
|
5
|
+
* migration) pivot on kill→relaunch and reinstall; both were only expressible as
|
|
6
|
+
* `@manual:M7` before. `background app for N seconds` already lives in gesture-patterns.
|
|
7
|
+
* Mobile-only: on a web project these hit the missing-template guard (SG-E020) and fail
|
|
8
|
+
* loud, same policy as every gesture.
|
|
9
|
+
*/
|
|
10
|
+
import { StepPattern } from '@sun-asterisk/sungen';
|
|
11
|
+
|
|
12
|
+
export const lifecyclePatterns: StepPattern[] = [
|
|
13
|
+
{
|
|
14
|
+
// `User restart the app` / `User restarts the app`. Must NOT match when a selectorRef is
|
|
15
|
+
// present — `tap [Restart Button]` belongs to the tap pattern, not here.
|
|
16
|
+
name: 'restart-app',
|
|
17
|
+
matcher: (step) => /\brestart(s)?\b/i.test(step.text) && /\bapp\b/i.test(step.text) && !step.selectorRef,
|
|
18
|
+
resolver: () => ({ templateName: 'restart-app-action', data: {}, comment: 'Restart the app (kill → relaunch → settle)' }),
|
|
19
|
+
priority: 16,
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
// `User reinstall the app` — needs the session to have installed from a build file
|
|
23
|
+
// (appium:app); the template fails loud with the fix when the cap is absent.
|
|
24
|
+
name: 'reinstall-app',
|
|
25
|
+
matcher: (step) => /\bre-?install(s)?\b/i.test(step.text) && /\bapp\b/i.test(step.text) && !step.selectorRef,
|
|
26
|
+
resolver: () => ({ templateName: 'reinstall-app-action', data: {}, comment: 'Reinstall the app (remove → install → launch)' }),
|
|
27
|
+
priority: 16,
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
// `User open deep link {{url}}` (or a quoted literal) — routes the app via a VIEW intent /
|
|
31
|
+
// XCUITest deepLink. THE entry for push-param / universal-link routing matrices (#603).
|
|
32
|
+
name: 'open-deep-link',
|
|
33
|
+
matcher: (step) => /\bdeep\s?-?link\b/i.test(step.text) && (!!step.dataRef || step.value != null) && !step.selectorRef,
|
|
34
|
+
resolver: (step) => ({
|
|
35
|
+
templateName: 'deep-link-action',
|
|
36
|
+
data: { dataRef: step.dataRef, url: step.value },
|
|
37
|
+
comment: `Open deep link ${step.dataRef ? `{{${step.dataRef}}}` : step.value}`,
|
|
38
|
+
}),
|
|
39
|
+
priority: 16,
|
|
40
|
+
},
|
|
41
|
+
];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device-log assertion pattern (issue #603).
|
|
3
|
+
*
|
|
4
|
+
* Makes SILENT failure modes and analytics observable: many mobile specs define behaviors whose
|
|
5
|
+
* only trace is a log line (fetch-failure-silent rules, analytics screen names). Android reads
|
|
6
|
+
* logcat, iOS syslog. Mobile-only — web projects hit SG-E020, same policy as the gestures.
|
|
7
|
+
*/
|
|
8
|
+
import { StepPattern } from '@sun-asterisk/sungen';
|
|
9
|
+
|
|
10
|
+
export const logPatterns: StepPattern[] = [
|
|
11
|
+
{
|
|
12
|
+
// `Then User see device log contains {{v}}` / `… contains "literal"`. No selectorRef — the
|
|
13
|
+
// element-scoped `contains` assertions all carry one, so there is no collision.
|
|
14
|
+
name: 'device-log-contains',
|
|
15
|
+
matcher: (step) =>
|
|
16
|
+
/\b(device\s+)?logs?\b/i.test(step.text) &&
|
|
17
|
+
/\bcontains?\b/i.test(step.text) &&
|
|
18
|
+
(!!step.dataRef || step.value != null) &&
|
|
19
|
+
!step.selectorRef,
|
|
20
|
+
resolver: (step) => ({
|
|
21
|
+
templateName: 'device-log-assertion',
|
|
22
|
+
data: { dataRef: step.dataRef, value: step.value },
|
|
23
|
+
comment: `Assert device log contains ${step.dataRef ? `{{${step.dataRef}}}` : step.value}`,
|
|
24
|
+
}),
|
|
25
|
+
priority: 17,
|
|
26
|
+
},
|
|
27
|
+
];
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Timing-window assertion patterns (issue #600).
|
|
3
|
+
*
|
|
4
|
+
* Auto-dismiss (~5s tooltip/popup) and validity-window (60s barcode) oracles: the DSL only
|
|
5
|
+
* had appear-waits. Priority 18 — these must outrank the generic visible/hidden assertions,
|
|
6
|
+
* whose matchers would otherwise swallow the `see [X] …` prefix.
|
|
7
|
+
*/
|
|
8
|
+
import { StepPattern } from '@sun-asterisk/sungen';
|
|
9
|
+
|
|
10
|
+
const SECONDS = /(\d+)\s*seconds?\b/i;
|
|
11
|
+
|
|
12
|
+
export const timingPatterns: StepPattern[] = [
|
|
13
|
+
{
|
|
14
|
+
// `Then User see [X] disappear within 5 seconds` — the element must vanish inside the window.
|
|
15
|
+
name: 'disappears-within',
|
|
16
|
+
matcher: (step) => /\bdisappears?\b/i.test(step.text) && /\bwithin\b/i.test(step.text) && SECONDS.test(step.text) && !!step.selectorRef,
|
|
17
|
+
resolver: (step, context) => {
|
|
18
|
+
const resolved = context.selectorResolver.resolveSelector(step.selectorRef!, context.featureName, step.elementType, step.nth);
|
|
19
|
+
const seconds = parseInt(step.text.match(SECONDS)![1], 10);
|
|
20
|
+
return {
|
|
21
|
+
templateName: 'disappears-within-assertion',
|
|
22
|
+
data: { ...resolved, seconds, selectorRef: step.selectorRef },
|
|
23
|
+
comment: `Assert ${step.selectorRef} disappears within ${seconds}s`,
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
priority: 18,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
// `Then User see [X] still visible after 3 seconds` — the element must survive the window.
|
|
30
|
+
name: 'still-visible-after',
|
|
31
|
+
matcher: (step) => /\bstill\s+visible\s+after\b/i.test(step.text) && SECONDS.test(step.text) && !!step.selectorRef,
|
|
32
|
+
resolver: (step, context) => {
|
|
33
|
+
const resolved = context.selectorResolver.resolveSelector(step.selectorRef!, context.featureName, step.elementType, step.nth);
|
|
34
|
+
const seconds = parseInt(step.text.match(SECONDS)![1], 10);
|
|
35
|
+
return {
|
|
36
|
+
templateName: 'still-visible-after-assertion',
|
|
37
|
+
data: { ...resolved, seconds, selectorRef: step.selectorRef },
|
|
38
|
+
comment: `Assert ${step.selectorRef} still visible after ${seconds}s`,
|
|
39
|
+
};
|
|
40
|
+
},
|
|
41
|
+
priority: 18,
|
|
42
|
+
},
|
|
43
|
+
];
|