@sudobility/testomniac_runner_service 0.1.45 → 0.1.47
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/analyzer/page-analyzer.d.ts +78 -1
- package/dist/analyzer/page-analyzer.d.ts.map +1 -1
- package/dist/analyzer/page-analyzer.js +1600 -6
- package/dist/analyzer/page-analyzer.js.map +1 -1
- package/dist/browser/control-snapshot.d.ts +4 -0
- package/dist/browser/control-snapshot.d.ts.map +1 -0
- package/dist/browser/control-snapshot.js +181 -0
- package/dist/browser/control-snapshot.js.map +1 -0
- package/dist/browser/dom-snapshot.d.ts.map +1 -1
- package/dist/browser/dom-snapshot.js +8 -0
- package/dist/browser/dom-snapshot.js.map +1 -1
- package/dist/browser/ui-snapshot.d.ts +9 -0
- package/dist/browser/ui-snapshot.d.ts.map +1 -0
- package/dist/browser/ui-snapshot.js +53 -0
- package/dist/browser/ui-snapshot.js.map +1 -0
- package/dist/expertise/content-expertise.d.ts +1 -0
- package/dist/expertise/content-expertise.d.ts.map +1 -1
- package/dist/expertise/content-expertise.js +38 -0
- package/dist/expertise/content-expertise.js.map +1 -1
- package/dist/expertise/tester/commerce-checks.d.ts +14 -0
- package/dist/expertise/tester/commerce-checks.d.ts.map +1 -0
- package/dist/expertise/tester/commerce-checks.js +132 -0
- package/dist/expertise/tester/commerce-checks.js.map +1 -0
- package/dist/expertise/tester/control-state.d.ts +31 -0
- package/dist/expertise/tester/control-state.d.ts.map +1 -0
- package/dist/expertise/tester/control-state.js +46 -0
- package/dist/expertise/tester/control-state.js.map +1 -0
- package/dist/expertise/tester/core-checks.d.ts +5 -0
- package/dist/expertise/tester/core-checks.d.ts.map +1 -0
- package/dist/expertise/tester/core-checks.js +46 -0
- package/dist/expertise/tester/core-checks.js.map +1 -0
- package/dist/expertise/tester/dialog-feedback-checks.d.ts +13 -0
- package/dist/expertise/tester/dialog-feedback-checks.d.ts.map +1 -0
- package/dist/expertise/tester/dialog-feedback-checks.js +82 -0
- package/dist/expertise/tester/dialog-feedback-checks.js.map +1 -0
- package/dist/expertise/tester/form-checks.d.ts +8 -0
- package/dist/expertise/tester/form-checks.d.ts.map +1 -0
- package/dist/expertise/tester/form-checks.js +50 -0
- package/dist/expertise/tester/form-checks.js.map +1 -0
- package/dist/expertise/tester/keyboard-disclosure-checks.d.ts +7 -0
- package/dist/expertise/tester/keyboard-disclosure-checks.d.ts.map +1 -0
- package/dist/expertise/tester/keyboard-disclosure-checks.js +46 -0
- package/dist/expertise/tester/keyboard-disclosure-checks.js.map +1 -0
- package/dist/expertise/tester/navigation-checks.d.ts +8 -0
- package/dist/expertise/tester/navigation-checks.d.ts.map +1 -0
- package/dist/expertise/tester/navigation-checks.js +64 -0
- package/dist/expertise/tester/navigation-checks.js.map +1 -0
- package/dist/expertise/tester/network-intent-checks.d.ts +7 -0
- package/dist/expertise/tester/network-intent-checks.d.ts.map +1 -0
- package/dist/expertise/tester/network-intent-checks.js +56 -0
- package/dist/expertise/tester/network-intent-checks.js.map +1 -0
- package/dist/expertise/tester/page-behavior-checks.d.ts +17 -0
- package/dist/expertise/tester/page-behavior-checks.d.ts.map +1 -0
- package/dist/expertise/tester/page-behavior-checks.js +144 -0
- package/dist/expertise/tester/page-behavior-checks.js.map +1 -0
- package/dist/expertise/tester/persistence-checks.d.ts +12 -0
- package/dist/expertise/tester/persistence-checks.d.ts.map +1 -0
- package/dist/expertise/tester/persistence-checks.js +109 -0
- package/dist/expertise/tester/persistence-checks.js.map +1 -0
- package/dist/expertise/tester/search-checks.d.ts +10 -0
- package/dist/expertise/tester/search-checks.d.ts.map +1 -0
- package/dist/expertise/tester/search-checks.js +111 -0
- package/dist/expertise/tester/search-checks.js.map +1 -0
- package/dist/expertise/tester/selection-control-checks.d.ts +7 -0
- package/dist/expertise/tester/selection-control-checks.d.ts.map +1 -0
- package/dist/expertise/tester/selection-control-checks.js +128 -0
- package/dist/expertise/tester/selection-control-checks.js.map +1 -0
- package/dist/expertise/tester/text-input-checks.d.ts +8 -0
- package/dist/expertise/tester/text-input-checks.d.ts.map +1 -0
- package/dist/expertise/tester/text-input-checks.js +194 -0
- package/dist/expertise/tester/text-input-checks.js.map +1 -0
- package/dist/expertise/tester/validation-checks.d.ts +10 -0
- package/dist/expertise/tester/validation-checks.d.ts.map +1 -0
- package/dist/expertise/tester/validation-checks.js +59 -0
- package/dist/expertise/tester/validation-checks.js.map +1 -0
- package/dist/expertise/tester-expertise.d.ts +0 -3
- package/dist/expertise/tester-expertise.d.ts.map +1 -1
- package/dist/expertise/tester-expertise.js +75 -49
- package/dist/expertise/tester-expertise.js.map +1 -1
- package/dist/expertise/types.d.ts +12 -1
- package/dist/expertise/types.d.ts.map +1 -1
- package/dist/extractors/form-extractor.d.ts +19 -0
- package/dist/extractors/form-extractor.d.ts.map +1 -1
- package/dist/extractors/form-extractor.js +271 -42
- package/dist/extractors/form-extractor.js.map +1 -1
- package/dist/orchestrator/test-element-executor.d.ts.map +1 -1
- package/dist/orchestrator/test-element-executor.js +74 -9
- package/dist/orchestrator/test-element-executor.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { classifyControlKind, findControlBySelector, findControlPeers, } from "./control-state";
|
|
2
|
+
export function checkSelectionState(expectation, context) {
|
|
3
|
+
const initial = findControlBySelector(context.initialControlStates, expectation.targetPath);
|
|
4
|
+
const final = findControlBySelector(context.finalControlStates, expectation.targetPath);
|
|
5
|
+
if (!final) {
|
|
6
|
+
return {
|
|
7
|
+
expected: expectation.description,
|
|
8
|
+
observed: `Target control not found for selector ${expectation.targetPath ?? "(unknown)"}`,
|
|
9
|
+
result: "error",
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
if (expectation.expectNoChange || final.disabled) {
|
|
13
|
+
if (!initial) {
|
|
14
|
+
return {
|
|
15
|
+
expected: expectation.description,
|
|
16
|
+
observed: "Disabled control was not present in the initial snapshot",
|
|
17
|
+
result: "error",
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
if (initial.checked !== final.checked ||
|
|
21
|
+
initial.selected !== final.selected ||
|
|
22
|
+
initial.value !== final.value) {
|
|
23
|
+
return {
|
|
24
|
+
expected: expectation.description,
|
|
25
|
+
observed: "Disabled control changed state after interaction",
|
|
26
|
+
result: "error",
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
expected: expectation.description,
|
|
31
|
+
observed: expectation.expectNoChange
|
|
32
|
+
? "Control did not respond to interaction"
|
|
33
|
+
: "Disabled control did not respond to interaction",
|
|
34
|
+
result: "pass",
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const kind = classifyControlKind(final);
|
|
38
|
+
switch (kind) {
|
|
39
|
+
case "radio":
|
|
40
|
+
return checkRadioSelection(expectation.description, final, context);
|
|
41
|
+
case "checkbox":
|
|
42
|
+
case "switch":
|
|
43
|
+
return checkCheckboxSelection(expectation.description, initial, final, context);
|
|
44
|
+
case "tab":
|
|
45
|
+
return checkTabSelection(expectation.description, final, context);
|
|
46
|
+
default:
|
|
47
|
+
return {
|
|
48
|
+
expected: expectation.description,
|
|
49
|
+
observed: `Control kind "${kind}" does not support selection assertions`,
|
|
50
|
+
result: "warning",
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function checkRadioSelection(description, final, context) {
|
|
55
|
+
const peers = findControlPeers(context.finalControlStates, final);
|
|
56
|
+
const checkedPeers = peers.filter(peer => peer.checked || peer.selected);
|
|
57
|
+
if (!(final.checked || final.selected)) {
|
|
58
|
+
return {
|
|
59
|
+
expected: description,
|
|
60
|
+
observed: "Radio control was not selected after interaction",
|
|
61
|
+
result: "error",
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
if (checkedPeers.length > 1) {
|
|
65
|
+
return {
|
|
66
|
+
expected: description,
|
|
67
|
+
observed: `Radio group has multiple selected controls (${checkedPeers.length})`,
|
|
68
|
+
result: "error",
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
expected: description,
|
|
73
|
+
observed: "Radio control selected itself and unselected the rest of its group",
|
|
74
|
+
result: "pass",
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function checkCheckboxSelection(description, initial, final, context) {
|
|
78
|
+
if (!final.checked) {
|
|
79
|
+
return {
|
|
80
|
+
expected: description,
|
|
81
|
+
observed: "Checkbox-like control is not checked after interaction",
|
|
82
|
+
result: "error",
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
const initialPeers = findControlPeers(context.initialControlStates, initial);
|
|
86
|
+
const finalPeers = findControlPeers(context.finalControlStates, final);
|
|
87
|
+
for (const peer of initialPeers) {
|
|
88
|
+
if (!peer.checked || peer.selector === final.selector)
|
|
89
|
+
continue;
|
|
90
|
+
const matchingFinal = finalPeers.find(candidate => candidate.selector === peer.selector);
|
|
91
|
+
if (matchingFinal && !matchingFinal.checked) {
|
|
92
|
+
return {
|
|
93
|
+
expected: description,
|
|
94
|
+
observed: `Checkbox interaction unexpectedly unchecked sibling control ${peer.selector}`,
|
|
95
|
+
result: "error",
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
expected: description,
|
|
101
|
+
observed: "Checkbox-like control checked itself without clearing other checked siblings",
|
|
102
|
+
result: "pass",
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function checkTabSelection(description, final, context) {
|
|
106
|
+
const peers = findControlPeers(context.finalControlStates, final);
|
|
107
|
+
const selectedPeers = peers.filter(peer => peer.selected);
|
|
108
|
+
if (!final.selected) {
|
|
109
|
+
return {
|
|
110
|
+
expected: description,
|
|
111
|
+
observed: "Tab did not become selected after interaction",
|
|
112
|
+
result: "error",
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
if (selectedPeers.length !== 1) {
|
|
116
|
+
return {
|
|
117
|
+
expected: description,
|
|
118
|
+
observed: `Tablist has ${selectedPeers.length} selected tabs instead of exactly one`,
|
|
119
|
+
result: "error",
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
expected: description,
|
|
124
|
+
observed: "Tab interaction resulted in a single selected tab",
|
|
125
|
+
result: "pass",
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=selection-control-checks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selection-control-checks.js","sourceRoot":"","sources":["../../../src/expertise/tester/selection-control-checks.ts"],"names":[],"mappings":"AACA,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,UAAU,mBAAmB,CACjC,WAIC,EACD,OAAyB;IAEzB,MAAM,OAAO,GAAG,qBAAqB,CACnC,OAAO,CAAC,oBAAoB,EAC5B,WAAW,CAAC,UAAU,CACvB,CAAC;IACF,MAAM,KAAK,GAAG,qBAAqB,CACjC,OAAO,CAAC,kBAAkB,EAC1B,WAAW,CAAC,UAAU,CACvB,CAAC;IAEF,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;YACL,QAAQ,EAAE,WAAW,CAAC,WAAW;YACjC,QAAQ,EAAE,yCAAyC,WAAW,CAAC,UAAU,IAAI,WAAW,EAAE;YAC1F,MAAM,EAAE,OAAO;SAChB,CAAC;IACJ,CAAC;IAED,IAAI,WAAW,CAAC,cAAc,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACjD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO;gBACL,QAAQ,EAAE,WAAW,CAAC,WAAW;gBACjC,QAAQ,EAAE,0DAA0D;gBACpE,MAAM,EAAE,OAAO;aAChB,CAAC;QACJ,CAAC;QAED,IACE,OAAO,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO;YACjC,OAAO,CAAC,QAAQ,KAAK,KAAK,CAAC,QAAQ;YACnC,OAAO,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK,EAC7B,CAAC;YACD,OAAO;gBACL,QAAQ,EAAE,WAAW,CAAC,WAAW;gBACjC,QAAQ,EAAE,kDAAkD;gBAC5D,MAAM,EAAE,OAAO;aAChB,CAAC;QACJ,CAAC;QAED,OAAO;YACL,QAAQ,EAAE,WAAW,CAAC,WAAW;YACjC,QAAQ,EAAE,WAAW,CAAC,cAAc;gBAClC,CAAC,CAAC,wCAAwC;gBAC1C,CAAC,CAAC,iDAAiD;YACrD,MAAM,EAAE,MAAM;SACf,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;IACxC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,OAAO;YACV,OAAO,mBAAmB,CAAC,WAAW,CAAC,WAAW,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;QACtE,KAAK,UAAU,CAAC;QAChB,KAAK,QAAQ;YACX,OAAO,sBAAsB,CAC3B,WAAW,CAAC,WAAW,EACvB,OAAO,EACP,KAAK,EACL,OAAO,CACR,CAAC;QACJ,KAAK,KAAK;YACR,OAAO,iBAAiB,CAAC,WAAW,CAAC,WAAW,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;QACpE;YACE,OAAO;gBACL,QAAQ,EAAE,WAAW,CAAC,WAAW;gBACjC,QAAQ,EAAE,iBAAiB,IAAI,yCAAyC;gBACxE,MAAM,EAAE,SAAS;aAClB,CAAC;IACN,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAC1B,WAAmB,EACnB,KAA4D,EAC5D,OAAyB;IAEzB,MAAM,KAAK,GAAG,gBAAgB,CAAC,OAAO,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;IAClE,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC;IAEzE,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvC,OAAO;YACL,QAAQ,EAAE,WAAW;YACrB,QAAQ,EAAE,kDAAkD;YAC5D,MAAM,EAAE,OAAO;SAChB,CAAC;IACJ,CAAC;IAED,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,OAAO;YACL,QAAQ,EAAE,WAAW;YACrB,QAAQ,EAAE,+CAA+C,YAAY,CAAC,MAAM,GAAG;YAC/E,MAAM,EAAE,OAAO;SAChB,CAAC;IACJ,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,WAAW;QACrB,QAAQ,EACN,oEAAoE;QACtE,MAAM,EAAE,MAAM;KACf,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAC7B,WAAmB,EACnB,OAAiD,EACjD,KAA4D,EAC5D,OAAyB;IAEzB,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO;YACL,QAAQ,EAAE,WAAW;YACrB,QAAQ,EAAE,wDAAwD;YAClE,MAAM,EAAE,OAAO;SAChB,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,gBAAgB,CAAC,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAC;IAC7E,MAAM,UAAU,GAAG,gBAAgB,CAAC,OAAO,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;IAEvE,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,QAAQ,KAAK,KAAK,CAAC,QAAQ;YAAE,SAAS;QAChE,MAAM,aAAa,GAAG,UAAU,CAAC,IAAI,CACnC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,CAClD,CAAC;QACF,IAAI,aAAa,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC;YAC5C,OAAO;gBACL,QAAQ,EAAE,WAAW;gBACrB,QAAQ,EAAE,+DAA+D,IAAI,CAAC,QAAQ,EAAE;gBACxF,MAAM,EAAE,OAAO;aAChB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,WAAW;QACrB,QAAQ,EACN,8EAA8E;QAChF,MAAM,EAAE,MAAM;KACf,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CACxB,WAAmB,EACnB,KAA4D,EAC5D,OAAyB;IAEzB,MAAM,KAAK,GAAG,gBAAgB,CAAC,OAAO,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;IAClE,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAE1D,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QACpB,OAAO;YACL,QAAQ,EAAE,WAAW;YACrB,QAAQ,EAAE,+CAA+C;YACzD,MAAM,EAAE,OAAO;SAChB,CAAC;IACJ,CAAC;IAED,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO;YACL,QAAQ,EAAE,WAAW;YACrB,QAAQ,EAAE,eAAe,aAAa,CAAC,MAAM,uCAAuC;YACpF,MAAM,EAAE,OAAO;SAChB,CAAC;IACJ,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,WAAW;QACrB,QAAQ,EAAE,mDAAmD;QAC7D,MAAM,EAAE,MAAM;KACf,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ExpertiseContext, Outcome } from "../types";
|
|
2
|
+
export declare function checkInputValue(expectation: {
|
|
3
|
+
description: string;
|
|
4
|
+
expectedValue?: string;
|
|
5
|
+
targetPath?: string;
|
|
6
|
+
expectNoChange?: boolean;
|
|
7
|
+
}, context: ExpertiseContext): Outcome;
|
|
8
|
+
//# sourceMappingURL=text-input-checks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-input-checks.d.ts","sourceRoot":"","sources":["../../../src/expertise/tester/text-input-checks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAQ1D,wBAAgB,eAAe,CAC7B,WAAW,EAAE;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,EACD,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAuFT"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { classifyControlKind, digitsOnly, findControlBySelector, normalizeWhitespace, } from "./control-state";
|
|
2
|
+
export function checkInputValue(expectation, context) {
|
|
3
|
+
const control = findControlBySelector(context.finalControlStates, expectation.targetPath);
|
|
4
|
+
if (!control) {
|
|
5
|
+
return {
|
|
6
|
+
expected: expectation.description,
|
|
7
|
+
observed: `Target control not found for selector ${expectation.targetPath ?? "(unknown)"}`,
|
|
8
|
+
result: "error",
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
if (expectation.expectNoChange || control.disabled) {
|
|
12
|
+
const initial = findControlBySelector(context.initialControlStates, expectation.targetPath);
|
|
13
|
+
if (!initial) {
|
|
14
|
+
return {
|
|
15
|
+
expected: expectation.description,
|
|
16
|
+
observed: "Disabled control was not present in the initial snapshot",
|
|
17
|
+
result: "error",
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
if (initial.value !== control.value) {
|
|
21
|
+
return {
|
|
22
|
+
expected: expectation.description,
|
|
23
|
+
observed: `Disabled control changed from "${initial.value}" to "${control.value}"`,
|
|
24
|
+
result: "error",
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
expected: expectation.description,
|
|
29
|
+
observed: expectation.expectNoChange
|
|
30
|
+
? "Control did not respond to user input"
|
|
31
|
+
: "Disabled control did not respond to user input",
|
|
32
|
+
result: "pass",
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
const expectedValue = expectation.expectedValue ?? "";
|
|
36
|
+
const actualValue = control.value ?? "";
|
|
37
|
+
const kind = classifyControlKind(control);
|
|
38
|
+
switch (kind) {
|
|
39
|
+
case "phone":
|
|
40
|
+
return checkPhoneInput(expectation.description, expectedValue, actualValue);
|
|
41
|
+
case "date":
|
|
42
|
+
return checkDateInput(expectation.description, expectedValue, actualValue);
|
|
43
|
+
case "number":
|
|
44
|
+
return checkNumberInput(expectation.description, expectedValue, actualValue);
|
|
45
|
+
case "password":
|
|
46
|
+
return checkPasswordInput(expectation.description, expectedValue, actualValue, control.passwordMasked, control.hasPasswordRevealControl);
|
|
47
|
+
case "select":
|
|
48
|
+
return checkSelectInput(expectation.description, expectedValue, control.selectedValues);
|
|
49
|
+
default:
|
|
50
|
+
return checkPlainTextInput(expectation.description, expectedValue, actualValue);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function checkPlainTextInput(description, expectedValue, actualValue) {
|
|
54
|
+
if (normalizeWhitespace(actualValue) !== normalizeWhitespace(expectedValue)) {
|
|
55
|
+
return {
|
|
56
|
+
expected: description,
|
|
57
|
+
observed: `Expected value "${expectedValue}" but found "${actualValue}"`,
|
|
58
|
+
result: "error",
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
expected: description,
|
|
63
|
+
observed: `Control accepted typed value "${actualValue}"`,
|
|
64
|
+
result: "pass",
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function checkPhoneInput(description, expectedValue, actualValue) {
|
|
68
|
+
const expectedDigits = digitsOnly(expectedValue);
|
|
69
|
+
const actualDigits = digitsOnly(actualValue);
|
|
70
|
+
const hasLetters = /[a-z]/i.test(actualValue);
|
|
71
|
+
if (hasLetters) {
|
|
72
|
+
return {
|
|
73
|
+
expected: description,
|
|
74
|
+
observed: `Phone input retained alphabetic characters: "${actualValue}"`,
|
|
75
|
+
result: "error",
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (!actualDigits || actualDigits !== expectedDigits) {
|
|
79
|
+
return {
|
|
80
|
+
expected: description,
|
|
81
|
+
observed: `Phone input did not preserve the typed digits. Expected ${expectedDigits}, got "${actualValue}"`,
|
|
82
|
+
result: "error",
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
expected: description,
|
|
87
|
+
observed: `Phone input accepted digits and formatted them as "${actualValue}"`,
|
|
88
|
+
result: "pass",
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function checkDateInput(description, expectedValue, actualValue) {
|
|
92
|
+
if (!actualValue) {
|
|
93
|
+
return {
|
|
94
|
+
expected: description,
|
|
95
|
+
observed: "Date input remained empty after typing",
|
|
96
|
+
result: "error",
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
if (/[a-z]/i.test(actualValue)) {
|
|
100
|
+
return {
|
|
101
|
+
expected: description,
|
|
102
|
+
observed: `Date input retained alphabetic characters: "${actualValue}"`,
|
|
103
|
+
result: "error",
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const expectedDigits = digitsOnly(expectedValue);
|
|
107
|
+
const actualDigits = digitsOnly(actualValue);
|
|
108
|
+
if (actualDigits.length < 6 ||
|
|
109
|
+
!expectedDigits.startsWith(actualDigits.slice(0, Math.min(actualDigits.length, expectedDigits.length)))) {
|
|
110
|
+
return {
|
|
111
|
+
expected: description,
|
|
112
|
+
observed: `Date input did not retain the typed date digits. Expected from "${expectedValue}", got "${actualValue}"`,
|
|
113
|
+
result: "error",
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
if (!/^[0-9/\-.]+$/.test(actualValue)) {
|
|
117
|
+
return {
|
|
118
|
+
expected: description,
|
|
119
|
+
observed: `Date input contains unexpected characters: "${actualValue}"`,
|
|
120
|
+
result: "error",
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
expected: description,
|
|
125
|
+
observed: `Date input accepted numeric entry as "${actualValue}"`,
|
|
126
|
+
result: "pass",
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function checkNumberInput(description, expectedValue, actualValue) {
|
|
130
|
+
if (!actualValue) {
|
|
131
|
+
return {
|
|
132
|
+
expected: description,
|
|
133
|
+
observed: "Number input remained empty after typing",
|
|
134
|
+
result: "error",
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
if (!/^-?\d+(\.\d+)?$/.test(actualValue)) {
|
|
138
|
+
return {
|
|
139
|
+
expected: description,
|
|
140
|
+
observed: `Number input contains non-numeric characters: "${actualValue}"`,
|
|
141
|
+
result: "error",
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
if (digitsOnly(actualValue) !== digitsOnly(expectedValue)) {
|
|
145
|
+
return {
|
|
146
|
+
expected: description,
|
|
147
|
+
observed: `Number input did not retain the expected digits. Expected "${expectedValue}", got "${actualValue}"`,
|
|
148
|
+
result: "error",
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
expected: description,
|
|
153
|
+
observed: `Number input accepted numeric entry "${actualValue}"`,
|
|
154
|
+
result: "pass",
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function checkPasswordInput(description, expectedValue, actualValue, passwordMasked, hasPasswordRevealControl) {
|
|
158
|
+
if (actualValue !== expectedValue) {
|
|
159
|
+
return {
|
|
160
|
+
expected: description,
|
|
161
|
+
observed: `Password input did not retain the typed value. Expected length ${expectedValue.length}, got "${actualValue}"`,
|
|
162
|
+
result: "error",
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
if (!passwordMasked && !hasPasswordRevealControl) {
|
|
166
|
+
return {
|
|
167
|
+
expected: description,
|
|
168
|
+
observed: "Password field no longer appears masked and no reveal control was detected",
|
|
169
|
+
result: "error",
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
expected: description,
|
|
174
|
+
observed: passwordMasked
|
|
175
|
+
? "Password field retained the typed value and remained masked"
|
|
176
|
+
: "Password field retained the typed value and has a reveal control",
|
|
177
|
+
result: "pass",
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
function checkSelectInput(description, expectedValue, selectedValues) {
|
|
181
|
+
if (!selectedValues.includes(expectedValue)) {
|
|
182
|
+
return {
|
|
183
|
+
expected: description,
|
|
184
|
+
observed: `Expected selected option "${expectedValue}" but found [${selectedValues.join(", ")}]`,
|
|
185
|
+
result: "error",
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
expected: description,
|
|
190
|
+
observed: `Select control chose "${expectedValue}"`,
|
|
191
|
+
result: "pass",
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=text-input-checks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-input-checks.js","sourceRoot":"","sources":["../../../src/expertise/tester/text-input-checks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ExpertiseContext, Outcome } from "../types";
|
|
2
|
+
export declare function checkRequiredErrorShownForField(expectation: {
|
|
3
|
+
description: string;
|
|
4
|
+
targetPath?: string;
|
|
5
|
+
}, context: ExpertiseContext): Outcome;
|
|
6
|
+
export declare function checkFieldErrorClearsAfterFix(expectation: {
|
|
7
|
+
description: string;
|
|
8
|
+
targetPath?: string;
|
|
9
|
+
}, context: ExpertiseContext): Outcome;
|
|
10
|
+
//# sourceMappingURL=validation-checks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-checks.d.ts","sourceRoot":"","sources":["../../../src/expertise/tester/validation-checks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAG1D,wBAAgB,+BAA+B,CAC7C,WAAW,EAAE;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,EACD,OAAO,EAAE,gBAAgB,GACxB,OAAO,CA4BT;AAED,wBAAgB,6BAA6B,CAC3C,WAAW,EAAE;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,EACD,OAAO,EAAE,gBAAgB,GACxB,OAAO,CA4CT"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { findControlBySelector } from "./control-state";
|
|
2
|
+
export function checkRequiredErrorShownForField(expectation, context) {
|
|
3
|
+
const target = findControlBySelector(context.finalControlStates, expectation.targetPath);
|
|
4
|
+
if (target && (target.invalid || Boolean(target.validationMessage))) {
|
|
5
|
+
return {
|
|
6
|
+
expected: expectation.description,
|
|
7
|
+
observed: `Field ${target.selector} shows invalid state or validation message`,
|
|
8
|
+
result: "pass",
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
if (hasErrorLikeText(context.html)) {
|
|
12
|
+
return {
|
|
13
|
+
expected: expectation.description,
|
|
14
|
+
observed: "Page shows visible validation-like error text",
|
|
15
|
+
result: "pass",
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
expected: expectation.description,
|
|
20
|
+
observed: "No field-specific invalid state or validation message was detected",
|
|
21
|
+
result: "error",
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export function checkFieldErrorClearsAfterFix(expectation, context) {
|
|
25
|
+
const initial = findControlBySelector(context.initialControlStates, expectation.targetPath);
|
|
26
|
+
const final = findControlBySelector(context.finalControlStates, expectation.targetPath);
|
|
27
|
+
if (final && (final.invalid || Boolean(final.validationMessage))) {
|
|
28
|
+
return {
|
|
29
|
+
expected: expectation.description,
|
|
30
|
+
observed: `Field ${final.selector} still shows invalid state after correction`,
|
|
31
|
+
result: "error",
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
if (initial &&
|
|
35
|
+
(initial.invalid || Boolean(initial.validationMessage)) &&
|
|
36
|
+
final) {
|
|
37
|
+
return {
|
|
38
|
+
expected: expectation.description,
|
|
39
|
+
observed: `Field ${final.selector} cleared its invalid state after correction`,
|
|
40
|
+
result: "pass",
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (!hasErrorLikeText(context.html)) {
|
|
44
|
+
return {
|
|
45
|
+
expected: expectation.description,
|
|
46
|
+
observed: "No visible validation-like error text remains after correction",
|
|
47
|
+
result: "pass",
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
expected: expectation.description,
|
|
52
|
+
observed: "Validation-like error text still appears after correction",
|
|
53
|
+
result: "warning",
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function hasErrorLikeText(html) {
|
|
57
|
+
return /(required|invalid|error|try again|must be|please enter|please select)/i.test(html);
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=validation-checks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-checks.js","sourceRoot":"","sources":["../../../src/expertise/tester/validation-checks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAExD,MAAM,UAAU,+BAA+B,CAC7C,WAGC,EACD,OAAyB;IAEzB,MAAM,MAAM,GAAG,qBAAqB,CAClC,OAAO,CAAC,kBAAkB,EAC1B,WAAW,CAAC,UAAU,CACvB,CAAC;IAEF,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,EAAE,CAAC;QACpE,OAAO;YACL,QAAQ,EAAE,WAAW,CAAC,WAAW;YACjC,QAAQ,EAAE,SAAS,MAAM,CAAC,QAAQ,4CAA4C;YAC9E,MAAM,EAAE,MAAM;SACf,CAAC;IACJ,CAAC;IAED,IAAI,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,OAAO;YACL,QAAQ,EAAE,WAAW,CAAC,WAAW;YACjC,QAAQ,EAAE,+CAA+C;YACzD,MAAM,EAAE,MAAM;SACf,CAAC;IACJ,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,WAAW,CAAC,WAAW;QACjC,QAAQ,EACN,oEAAoE;QACtE,MAAM,EAAE,OAAO;KAChB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,6BAA6B,CAC3C,WAGC,EACD,OAAyB;IAEzB,MAAM,OAAO,GAAG,qBAAqB,CACnC,OAAO,CAAC,oBAAoB,EAC5B,WAAW,CAAC,UAAU,CACvB,CAAC;IACF,MAAM,KAAK,GAAG,qBAAqB,CACjC,OAAO,CAAC,kBAAkB,EAC1B,WAAW,CAAC,UAAU,CACvB,CAAC;IAEF,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,EAAE,CAAC;QACjE,OAAO;YACL,QAAQ,EAAE,WAAW,CAAC,WAAW;YACjC,QAAQ,EAAE,SAAS,KAAK,CAAC,QAAQ,6CAA6C;YAC9E,MAAM,EAAE,OAAO;SAChB,CAAC;IACJ,CAAC;IAED,IACE,OAAO;QACP,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;QACvD,KAAK,EACL,CAAC;QACD,OAAO;YACL,QAAQ,EAAE,WAAW,CAAC,WAAW;YACjC,QAAQ,EAAE,SAAS,KAAK,CAAC,QAAQ,6CAA6C;YAC9E,MAAM,EAAE,MAAM;SACf,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,OAAO;YACL,QAAQ,EAAE,WAAW,CAAC,WAAW;YACjC,QAAQ,EACN,gEAAgE;YAClE,MAAM,EAAE,MAAM;SACf,CAAC;IACJ,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,WAAW,CAAC,WAAW;QACjC,QAAQ,EAAE,2DAA2D;QACrE,MAAM,EAAE,SAAS;KAClB,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY;IACpC,OAAO,wEAAwE,CAAC,IAAI,CAClF,IAAI,CACL,CAAC;AACJ,CAAC"}
|
|
@@ -7,8 +7,5 @@ export declare class TesterExpertise implements Expertise {
|
|
|
7
7
|
name: string;
|
|
8
8
|
evaluate(context: ExpertiseContext): Outcome[];
|
|
9
9
|
private checkExpectation;
|
|
10
|
-
private checkPageLoaded;
|
|
11
|
-
private checkNoConsoleErrors;
|
|
12
|
-
private checkNoNetworkErrors;
|
|
13
10
|
}
|
|
14
11
|
//# sourceMappingURL=tester-expertise.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tester-expertise.d.ts","sourceRoot":"","sources":["../../src/expertise/tester-expertise.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tester-expertise.d.ts","sourceRoot":"","sources":["../../src/expertise/tester-expertise.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAiDpE;;;GAGG;AACH,qBAAa,eAAgB,YAAW,SAAS;IAC/C,IAAI,SAAY;IAEhB,QAAQ,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,EAAE;IAc9C,OAAO,CAAC,gBAAgB;CAmFzB"}
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
import { ExpectationSeverity } from "@sudobility/testomniac_types";
|
|
2
|
+
import { checkNoConsoleErrors, checkNoNetworkErrors, checkPageLoaded, } from "./tester/core-checks";
|
|
3
|
+
import { checkInputValue } from "./tester/text-input-checks";
|
|
4
|
+
import { checkSelectionState } from "./tester/selection-control-checks";
|
|
5
|
+
import { checkFormSubmittedSuccessfully, checkValidationMessageVisible, } from "./tester/form-checks";
|
|
6
|
+
import { checkCartSummaryChanged, checkCollectionOrderChanged, checkCountChanged, } from "./tester/commerce-checks";
|
|
7
|
+
import { checkNavigationOrStateChanged, checkUrlUnchanged, } from "./tester/navigation-checks";
|
|
8
|
+
import { checkLoadingCompletes, checkMediaLoaded, checkModalOpened, checkPageResponsive, checkVideoPlayable, } from "./tester/page-behavior-checks";
|
|
9
|
+
import { checkFieldErrorClearsAfterFix, checkRequiredErrorShownForField, } from "./tester/validation-checks";
|
|
10
|
+
import { checkNetworkRequestMade } from "./tester/network-intent-checks";
|
|
11
|
+
import { checkEmptyStateVisible, checkResultsChanged, } from "./tester/search-checks";
|
|
12
|
+
import { checkDialogClosed, checkFeedbackVisible, checkFocusReturned, } from "./tester/dialog-feedback-checks";
|
|
13
|
+
import { checkBackNavigationRestoresState, checkForwardNavigationReappliesState, checkStatePersistsAfterReload, } from "./tester/persistence-checks";
|
|
14
|
+
import { checkExpandedStateChanged } from "./tester/keyboard-disclosure-checks";
|
|
1
15
|
/**
|
|
2
16
|
* Checks each test element expectation is met.
|
|
3
17
|
* Creates error outcomes for unmet expectations.
|
|
@@ -8,71 +22,83 @@ export class TesterExpertise {
|
|
|
8
22
|
const outcomes = [];
|
|
9
23
|
for (const expectation of context.expectations) {
|
|
10
24
|
const result = this.checkExpectation(expectation, context);
|
|
11
|
-
outcomes.push(
|
|
25
|
+
outcomes.push({
|
|
26
|
+
...result,
|
|
27
|
+
severity: expectation.severity,
|
|
28
|
+
});
|
|
12
29
|
}
|
|
13
30
|
return outcomes;
|
|
14
31
|
}
|
|
15
32
|
checkExpectation(expectation, context) {
|
|
16
33
|
switch (expectation.expectationType) {
|
|
17
34
|
case "page_loaded":
|
|
18
|
-
return
|
|
35
|
+
return checkPageLoaded(context, expectation.description);
|
|
19
36
|
case "no_console_errors":
|
|
20
|
-
return
|
|
37
|
+
return checkNoConsoleErrors(context, expectation.description);
|
|
21
38
|
case "no_network_errors":
|
|
22
|
-
return
|
|
39
|
+
return checkNoNetworkErrors(context, expectation.description);
|
|
40
|
+
case "input_value":
|
|
41
|
+
return checkInputValue(expectation, context);
|
|
42
|
+
case "element_checked":
|
|
43
|
+
case "element_unchecked":
|
|
44
|
+
return checkSelectionState(expectation, context);
|
|
45
|
+
case "validation_message_visible":
|
|
46
|
+
return checkValidationMessageVisible(expectation, context);
|
|
47
|
+
case "form_submitted_successfully":
|
|
48
|
+
return checkFormSubmittedSuccessfully(expectation, context);
|
|
49
|
+
case "required_error_shown_for_field":
|
|
50
|
+
return checkRequiredErrorShownForField(expectation, context);
|
|
51
|
+
case "field_error_clears_after_fix":
|
|
52
|
+
return checkFieldErrorClearsAfterFix(expectation, context);
|
|
53
|
+
case "cart_summary_changed":
|
|
54
|
+
return checkCartSummaryChanged(expectation, context);
|
|
55
|
+
case "count_changed":
|
|
56
|
+
return checkCountChanged(expectation, context);
|
|
57
|
+
case "network_request_made":
|
|
58
|
+
return checkNetworkRequestMade(expectation, context);
|
|
59
|
+
case "dialog_closed":
|
|
60
|
+
return checkDialogClosed(expectation, context);
|
|
61
|
+
case "focus_returned":
|
|
62
|
+
return checkFocusReturned(expectation, context);
|
|
63
|
+
case "feedback_visible":
|
|
64
|
+
return checkFeedbackVisible(expectation, context);
|
|
65
|
+
case "state_persists_after_reload":
|
|
66
|
+
return checkStatePersistsAfterReload(expectation, context);
|
|
67
|
+
case "back_navigation_restores_state":
|
|
68
|
+
return checkBackNavigationRestoresState(expectation, context);
|
|
69
|
+
case "forward_navigation_reapplies_state":
|
|
70
|
+
return checkForwardNavigationReappliesState(expectation, context);
|
|
71
|
+
case "expanded_state_changed":
|
|
72
|
+
return checkExpandedStateChanged(expectation, context);
|
|
73
|
+
case "results_changed":
|
|
74
|
+
return checkResultsChanged(expectation, context);
|
|
75
|
+
case "collection_order_changed":
|
|
76
|
+
return checkCollectionOrderChanged(expectation, context);
|
|
77
|
+
case "empty_state_visible":
|
|
78
|
+
return checkEmptyStateVisible(expectation, context);
|
|
79
|
+
case "url_unchanged":
|
|
80
|
+
return checkUrlUnchanged(expectation, context);
|
|
81
|
+
case "navigation_or_state_changed":
|
|
82
|
+
return checkNavigationOrStateChanged(expectation, context);
|
|
83
|
+
case "page_responsive":
|
|
84
|
+
return checkPageResponsive(expectation, context);
|
|
85
|
+
case "loading_completes":
|
|
86
|
+
return checkLoadingCompletes(expectation, context);
|
|
87
|
+
case "modal_opened":
|
|
88
|
+
return checkModalOpened(expectation, context);
|
|
89
|
+
case "media_loaded":
|
|
90
|
+
return checkMediaLoaded(expectation, context);
|
|
91
|
+
case "video_playable":
|
|
92
|
+
return checkVideoPlayable(expectation, context);
|
|
23
93
|
default:
|
|
24
94
|
// For expectations we don't have specific logic for yet, pass them
|
|
25
95
|
return {
|
|
26
96
|
expected: expectation.description,
|
|
27
97
|
observed: "Check not implemented — assumed pass",
|
|
28
98
|
result: "pass",
|
|
99
|
+
severity: ExpectationSeverity.Info,
|
|
29
100
|
};
|
|
30
101
|
}
|
|
31
102
|
}
|
|
32
|
-
checkPageLoaded(context, description) {
|
|
33
|
-
const hasHtml = context.html.length > 0 && context.html.includes("<");
|
|
34
|
-
if (!hasHtml) {
|
|
35
|
-
return {
|
|
36
|
-
expected: description,
|
|
37
|
-
observed: "Page returned empty or non-HTML response",
|
|
38
|
-
result: "error",
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
return {
|
|
42
|
-
expected: description,
|
|
43
|
-
observed: "Page loaded successfully with HTML content",
|
|
44
|
-
result: "pass",
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
checkNoConsoleErrors(context, description) {
|
|
48
|
-
const errors = context.consoleLogs.filter(log => log.toLowerCase().startsWith("error") || log.includes("[ERROR]"));
|
|
49
|
-
if (errors.length > 0) {
|
|
50
|
-
return {
|
|
51
|
-
expected: description,
|
|
52
|
-
observed: `${errors.length} console error(s): ${errors[0]}`,
|
|
53
|
-
result: "error",
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
return {
|
|
57
|
-
expected: description,
|
|
58
|
-
observed: "No console errors detected",
|
|
59
|
-
result: "pass",
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
checkNoNetworkErrors(context, description) {
|
|
63
|
-
const errors = context.networkLogs.filter(log => log.status >= 400);
|
|
64
|
-
if (errors.length > 0) {
|
|
65
|
-
return {
|
|
66
|
-
expected: description,
|
|
67
|
-
observed: `${errors.length} network error(s): ${errors[0].url} (${errors[0].status})`,
|
|
68
|
-
result: "error",
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
return {
|
|
72
|
-
expected: description,
|
|
73
|
-
observed: "No network errors detected",
|
|
74
|
-
result: "pass",
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
103
|
}
|
|
78
104
|
//# sourceMappingURL=tester-expertise.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tester-expertise.js","sourceRoot":"","sources":["../../src/expertise/tester-expertise.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tester-expertise.js","sourceRoot":"","sources":["../../src/expertise/tester-expertise.ts"],"names":[],"mappings":"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"}
|