Skip to content

Commit d2201eb

Browse files
committed
fix(android): name the placeholder in a fill verification failure
A fill mismatch reported the raw dump text as actual, which on modern Android is the field's hint when the field is empty. The observed node now carries the helper's hint-showing fact and the hint itself, so a placeholder read as the value is visible in the failure details. Refs #2903, #2634.
1 parent 34f2eb1 commit d2201eb

4 files changed

Lines changed: 46 additions & 2 deletions

File tree

‎packages/platform-android/src/__tests__/fill-diagnostics.test.ts‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ function node(overrides: Partial<AndroidFillVerificationNode>): AndroidFillVerif
1313
password: false,
1414
inputMethodOwned: false,
1515
area: 0,
16+
hintShowing: false,
17+
placeholder: null,
1618
...overrides,
1719
};
1820
}
@@ -85,3 +87,25 @@ test('buildFillFailureDetails redacts common masked field glyphs', () => {
8587
assert.doesNotMatch(JSON.stringify(details), /Secret123|\*|•|●/);
8688
}
8789
});
90+
91+
// A field whose value the app rewrites, or an empty field dumping its hint as `text`, fails with the
92+
// raw dump text as `actual`. The node facts say whether that text was the field's placeholder.
93+
test('buildFillFailureDetails carries the hint-showing fact and the placeholder on the observed node', () => {
94+
const details = buildFillFailureDetails('Acme Ltd', {
95+
ok: false,
96+
actual: 'e.g. Merchant',
97+
reason: 'text_mismatch',
98+
targetInput: node({ text: 'e.g. Merchant', hintShowing: true, placeholder: 'e.g. Merchant' }),
99+
actualInput: node({
100+
text: 'e.g. Merchant',
101+
focused: true,
102+
hintShowing: true,
103+
placeholder: 'e.g. Merchant',
104+
}),
105+
});
106+
107+
assert.equal(details.expected, 'Acme Ltd');
108+
assert.equal(details.actual, 'e.g. Merchant');
109+
assert.equal(details.actualInput?.hintShowing, true);
110+
assert.equal(details.actualInput?.placeholder, 'e.g. Merchant');
111+
});

‎packages/platform-android/src/__tests__/text-input-fill.test.ts‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,20 @@ test('verifyAndroidFilledTextInHierarchy treats hint-only text as an empty value
430430
);
431431
assert.equal(verification.ok, false);
432432
assert.equal(verification.actual, 'Search settings');
433+
// The failure names the placeholder the dump text was, so "actual" is not read as a typed value.
434+
assert.equal(verification.actualInput?.hintShowing, true);
435+
});
436+
437+
test('verifyAndroidFilledTextInHierarchy carries the helper hint onto the observed node', () => {
438+
const verification = verifyAndroidFilledTextInHierarchy(
439+
'<?xml version="1.0" encoding="UTF-8"?><hierarchy><node package="com.example" class="android.widget.EditText" text="Acme" hint="e.g. Merchant" hint-showing="false" focused="true" bounds="[0,0][200,100]"/></hierarchy>',
440+
10,
441+
10,
442+
'Acme Ltd',
443+
);
444+
assert.equal(verification.ok, false);
445+
assert.equal(verification.actualInput?.placeholder, 'e.g. Merchant');
446+
assert.equal(verification.actualInput?.hintShowing, false);
433447
});
434448

435449
test('verifyAndroidFilledTextInHierarchy still refuses a non-empty field for an empty expectation', () => {

‎packages/platform-android/src/fill-diagnostics.ts‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ export type AndroidFillVerificationNode = {
1010
password: boolean;
1111
inputMethodOwned: boolean;
1212
area: number;
13+
/**
14+
* Helper-only fact: the node's dump `text` is its HINT, so the field itself is empty. Reported on
15+
* a mismatch so a placeholder read as the value is visible in the failure, not only in the log.
16+
*/
17+
hintShowing: boolean;
18+
/** The field's hint text when the helper supplied it, whether or not it is showing. */
19+
placeholder: string | null;
1320
};
1421

1522
export type FillFailureReason = 'ime_capture' | 'masked_unverified' | 'text_mismatch';

‎packages/platform-android/src/fill-verification.ts‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ export type { AndroidFillVerification } from './fill-diagnostics.ts';
2424

2525
type AndroidFillVerificationCandidate = AndroidFillVerificationNode & {
2626
editText: boolean;
27-
// Helper-only fact: the node's dump text is its HINT, so the field itself is empty.
28-
hintShowing: boolean;
2927
};
3028

3129
type AndroidTextAtPointInspection = {
@@ -410,6 +408,7 @@ function androidFillCandidateFromNode(
410408
area,
411409
editText: isEditTextClass(node.className ?? ''),
412410
hintShowing: node.hintShowing === true,
411+
placeholder: node.hint ?? null,
413412
};
414413
}
415414

0 commit comments

Comments
 (0)