mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-02 11:07:10 +00:00
test(chrome): compare the secure fact across both producers
it is the fourth fact the dump and the web runtime derive independently, and the one that decides whether a typed value is written into the shared record. three-valued, so the fixture guard requires all three states rather than both polarities.
This commit is contained in:
1 parent
6aecccd2d6
commit
9a920444b3
4 files changed
+67
No files matched your search
@@ -10,6 +10,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"slices"
|
"slices"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -51,6 +52,11 @@ type elementFacts struct {
|
|||||||
editable bool
|
editable bool
|
||||||
scrollable bool
|
scrollable bool
|
||||||
hintText string
|
hintText string
|
||||||
|
// secure is three-valued: "true", "false", or "" where the producer states
|
||||||
|
// nothing, which android states for every element. It decides whether a
|
||||||
|
// typed value may be written into the shared record, so the two producers
|
||||||
|
// disagreeing about it writes a credential into a run's trace.
|
||||||
|
secure string
|
||||||
// handleClickable and handleEditable are the same facts on the ax element a
|
// handleClickable and handleEditable are the same facts on the ax element a
|
||||||
// spec reaches through state.ax.find, a third place they are computed and the
|
// spec reaches through state.ax.find, a third place they are computed and the
|
||||||
// one that has twice been the odd one out: clickable answered a hardcoded
|
// one that has twice been the odd one out: clickable answered a hardcoded
|
||||||
@@ -100,6 +106,7 @@ func TestHierarchy_DerivesTheSameFactsAsTheWebRuntime(t *testing.T) {
|
|||||||
requireEveryElementNamed(t, "the hierarchy dump", fromDump)
|
requireEveryElementNamed(t, "the hierarchy dump", fromDump)
|
||||||
requireEveryElementNamed(t, "the web runtime", fromWebRuntime)
|
requireEveryElementNamed(t, "the web runtime", fromWebRuntime)
|
||||||
requireBothPolarities(t, fromWebRuntime)
|
requireBothPolarities(t, fromWebRuntime)
|
||||||
|
requireEverySecureState(t, fromWebRuntime)
|
||||||
requireTheHandleAgreesWithTheEnumeration(t, fromWebRuntime)
|
requireTheHandleAgreesWithTheEnumeration(t, fromWebRuntime)
|
||||||
compareEnumeratedElements(t, fromDump, fromWebRuntime)
|
compareEnumeratedElements(t, fromDump, fromWebRuntime)
|
||||||
compareDerivedFacts(t, fromDump, fromWebRuntime)
|
compareDerivedFacts(t, fromDump, fromWebRuntime)
|
||||||
@@ -127,6 +134,7 @@ func factsFromHierarchyDump(t *testing.T, dump string) []factRow {
|
|||||||
editable: element.Editable,
|
editable: element.Editable,
|
||||||
scrollable: element.Attributes["scrollable"] == "true",
|
scrollable: element.Attributes["scrollable"] == "true",
|
||||||
hintText: element.Attributes["hintText"],
|
hintText: element.Attributes["hintText"],
|
||||||
|
secure: secureFromDump(element),
|
||||||
positiveBounds: hasPositiveBounds(
|
positiveBounds: hasPositiveBounds(
|
||||||
element.Bounds.Width(),
|
element.Bounds.Width(),
|
||||||
element.Bounds.Height(),
|
element.Bounds.Height(),
|
||||||
@@ -175,6 +183,7 @@ func factsFromWebRuntime(
|
|||||||
HintText string `json:"hintText"`
|
HintText string `json:"hintText"`
|
||||||
HandleClickable bool `json:"handleClickable"`
|
HandleClickable bool `json:"handleClickable"`
|
||||||
HandleEditable bool `json:"handleEditable"`
|
HandleEditable bool `json:"handleEditable"`
|
||||||
|
Secure *bool `json:"secure"`
|
||||||
Width int `json:"width"`
|
Width int `json:"width"`
|
||||||
Height int `json:"height"`
|
Height int `json:"height"`
|
||||||
}
|
}
|
||||||
@@ -194,6 +203,7 @@ func factsFromWebRuntime(
|
|||||||
hintText: item.HintText,
|
hintText: item.HintText,
|
||||||
handleClickable: item.HandleClickable,
|
handleClickable: item.HandleClickable,
|
||||||
handleEditable: item.HandleEditable,
|
handleEditable: item.HandleEditable,
|
||||||
|
secure: secureFromWebRuntime(item.Secure),
|
||||||
positiveBounds: hasPositiveBounds(item.Width, item.Height),
|
positiveBounds: hasPositiveBounds(item.Width, item.Height),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -201,6 +211,24 @@ func factsFromWebRuntime(
|
|||||||
return rows
|
return rows
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// secureFromDump and secureFromWebRuntime read the same three-valued fact off
|
||||||
|
// the two producers. The dump leaves the field out entirely for an element it
|
||||||
|
// states nothing about, the web runtime reports null for it, and both mean the
|
||||||
|
// same thing: unknown, not "not a secure entry".
|
||||||
|
func secureFromDump(element *hierarchy.Element) string {
|
||||||
|
if !element.SecureReported() {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return strconv.FormatBool(element.Secure)
|
||||||
|
}
|
||||||
|
|
||||||
|
func secureFromWebRuntime(secure *bool) string {
|
||||||
|
if secure == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return strconv.FormatBool(*secure)
|
||||||
|
}
|
||||||
|
|
||||||
// hasPositiveBounds is the positiveBounds fact of pkg/spec/src/targets.ts,
|
// hasPositiveBounds is the positiveBounds fact of pkg/spec/src/targets.ts,
|
||||||
// applied to both producers so the geometry comparison cannot drift from the
|
// applied to both producers so the geometry comparison cannot drift from the
|
||||||
// rule it stands in for.
|
// rule it stands in for.
|
||||||
@@ -262,6 +290,27 @@ func requireBothPolarities(t *testing.T, rows []factRow) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// requireEverySecureState is requireBothPolarities for the one fact that is not
|
||||||
|
// a boolean. A fixture holding no password entry would compare "false" against
|
||||||
|
// "false" over the whole page and pass while proving nothing about the state
|
||||||
|
// that decides whether a typed value may be written down.
|
||||||
|
func requireEverySecureState(t *testing.T, rows []factRow) {
|
||||||
|
t.Helper()
|
||||||
|
seen := map[string]bool{}
|
||||||
|
for _, row := range rows {
|
||||||
|
seen[row.facts.secure] = true
|
||||||
|
}
|
||||||
|
for _, state := range []string{"true", "false", ""} {
|
||||||
|
if !seen[state] {
|
||||||
|
t.Errorf(
|
||||||
|
"the fixture no longer holds an element the web runtime reports "+
|
||||||
|
"secure=%q for, so comparing that state proves nothing",
|
||||||
|
state,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// requireTheHandleAgreesWithTheEnumeration compares the V8 host against itself.
|
// requireTheHandleAgreesWithTheEnumeration compares the V8 host against itself.
|
||||||
// An element a spec reaches through state.ax and the same element in the
|
// An element a spec reaches through state.ax and the same element in the
|
||||||
// enumeration must be clickable, and typeable, to the same degree, or a spec
|
// enumeration must be clickable, and typeable, to the same degree, or a spec
|
||||||
@@ -371,6 +420,17 @@ func compareDerivedFacts(t *testing.T, fromDump, fromWebRuntime []factRow) {
|
|||||||
web.hintText,
|
web.hintText,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if dump.secure != web.secure {
|
||||||
|
t.Errorf(
|
||||||
|
"%q (<%s>): the hierarchy dump derives secure=%q, the web runtime "+
|
||||||
|
"derives secure=%q; one host would write into the record a value "+
|
||||||
|
"the other redacts",
|
||||||
|
row.id,
|
||||||
|
dump.tag,
|
||||||
|
dump.secure,
|
||||||
|
web.secure,
|
||||||
|
)
|
||||||
|
}
|
||||||
for _, fact := range []struct {
|
for _, fact := range []struct {
|
||||||
name string
|
name string
|
||||||
dump bool
|
dump bool
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
<button id="shadow-save">save</button>
|
<button id="shadow-save">save</button>
|
||||||
<button id="shadow-cancel" disabled>cancel</button>
|
<button id="shadow-cancel" disabled>cancel</button>
|
||||||
<input id="shadow-amount" type="text" value="10" placeholder="0.00" />
|
<input id="shadow-amount" type="text" value="10" placeholder="0.00" />
|
||||||
|
<input id="shadow-password" type="password" placeholder="Password" />
|
||||||
<div id="shadow-plain">plain</div>
|
<div id="shadow-plain">plain</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="shadow-scroller"><div id="shadow-scroller-content"></div></div>`;
|
<div id="shadow-scroller"><div id="shadow-scroller-content"></div></div>`;
|
||||||
|
|||||||
@@ -61,6 +61,7 @@
|
|||||||
<input id="hint-aria" type="text" aria-label="Search" placeholder="Type here" name="q" />
|
<input id="hint-aria" type="text" aria-label="Search" placeholder="Type here" name="q" />
|
||||||
<input id="hint-placeholder" type="text" placeholder="What's this for?" name="note-field" />
|
<input id="hint-placeholder" type="text" placeholder="What's this for?" name="note-field" />
|
||||||
<input id="hint-name" type="text" name="reference-field" />
|
<input id="hint-name" type="text" name="reference-field" />
|
||||||
|
<input id="password" type="password" placeholder="Password" />
|
||||||
<input id="agree" type="checkbox" placeholder="not a hint" />
|
<input id="agree" type="checkbox" placeholder="not a hint" />
|
||||||
<textarea id="notes"></textarea>
|
<textarea id="notes"></textarea>
|
||||||
<!-- contenteditable is INHERITED, so #bio-word answers isContentEditable
|
<!-- contenteditable is INHERITED, so #bio-word answers isContentEditable
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ type AxHandle = {
|
|||||||
attrs?: Record<string, string>;
|
attrs?: Record<string, string>;
|
||||||
clickable?: boolean;
|
clickable?: boolean;
|
||||||
editable?: boolean;
|
editable?: boolean;
|
||||||
|
secure?: boolean | null;
|
||||||
};
|
};
|
||||||
type Ax = { find(selector: unknown): AxHandle | undefined };
|
type Ax = { find(selector: unknown): AxHandle | undefined };
|
||||||
|
|
||||||
@@ -50,6 +51,10 @@ function domFacts(): unknown[] {
|
|||||||
hintText: handle?.attrs?.hintText ?? "",
|
hintText: handle?.attrs?.hintText ?? "",
|
||||||
handleClickable: handle?.clickable ?? false,
|
handleClickable: handle?.clickable ?? false,
|
||||||
handleEditable: handle?.editable ?? false,
|
handleEditable: handle?.editable ?? false,
|
||||||
|
// Three-valued, so it stays null rather than collapsing onto false: the Go
|
||||||
|
// side compares it against a dump that leaves the fact out entirely for an
|
||||||
|
// element no producer states it for.
|
||||||
|
secure: handle?.secure ?? null,
|
||||||
width: target.width ?? 0,
|
width: target.width ?? 0,
|
||||||
height: target.height ?? 0,
|
height: target.height ?? 0,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in new issue
Block a user