@@ -12,11 +12,27 @@ HOST="$PWD/Headless.app/Contents/MacOS/Headless"
1212
1313PORT=$(( 43000 + RANDOM % 1000 ))
1414RUNTIME=" /tmp/headless-$( id -u) "
15+ mkdir -p " $RUNTIME "
16+ chmod 700 " $RUNTIME "
1517export HEADLESS_SOCKET=" $RUNTIME /macos-e2e-$$ .sock"
1618export HEADLESS_ARTIFACT_DIR=" $RUNTIME /artifacts-macos-e2e-$$ "
1719export HEADLESS_HOST_EXECUTABLE=" $HOST "
1820export HEADLESS_FIXTURE_PORT=" $PORT "
1921LOG=" $( mktemp " ${TMPDIR:-/ tmp} /headless-macos-e2e.XXXXXX" ) "
22+ HOST_LOG=" $( mktemp " ${TMPDIR:-/ tmp} /headless-macos-host.XXXXXX" ) "
23+ export HEADLESS_HOST_LOG=" $HOST_LOG "
24+ STEP=" boot"
25+
26+ fail () {
27+ trap - ERR
28+ print -u2 " macOS E2E failed during: $STEP "
29+ print -u2 " ---- fixture log ----"
30+ cat " $LOG " >&2 || true
31+ print -u2 " ---- host log ----"
32+ cat " $HOST_LOG " >&2 || true
33+ exit 1
34+ }
35+ trap ' fail' ERR
2036
2137node Tests/fixture-server.mjs > " $LOG " 2>&1 &
2238FIXTURE_PID=$!
@@ -25,27 +41,40 @@ cleanup() {
2541 " $CLI " stop > /dev/null 2>&1 || true
2642 kill " $FIXTURE_PID " > /dev/null 2>&1 || true
2743 rm -rf " $HEADLESS_ARTIFACT_DIR "
28- rm -f " $LOG "
44+ rm -f " $LOG " " $HOST_LOG "
2945}
3046trap cleanup EXIT INT TERM
3147
48+ STEP=" fixture-server"
3249for _ in {1..100}; do
3350 curl -fsS " http://127.0.0.1:$PORT /designers/dashboard" > /dev/null 2>&1 && break
3451 sleep 0.05
3552done
3653curl -fsS " http://127.0.0.1:$PORT /designers/dashboard" > /dev/null
3754
38- START_RESULT=" $( " $CLI " start) "
39- echo " $START_RESULT " | grep -q ' "ready":true'
55+ STEP=" start-host"
56+ START_RESULT=" $( " $CLI " start) " || {
57+ print -u2 " headless start failed:"
58+ print -u2 " $START_RESULT "
59+ fail
60+ }
61+ echo " $START_RESULT " | grep -q ' "ready":true' || {
62+ print -u2 " host did not become ready: $START_RESULT "
63+ fail
64+ }
65+ echo " ▸ host ready"
66+ STEP=" tcp-check"
4067HOST_PID=" $( echo " $START_RESULT " | sed -n ' s/.*"pid":\([0-9][0-9]*\).*/\1/p' ) "
4168test -n " $HOST_PID "
4269if lsof -nP -a -p " $HOST_PID " -iTCP -sTCP:LISTEN 2> /dev/null | grep -q LISTEN; then
4370 echo " Headless host opened an unexpected TCP listener" >&2
44- exit 1
71+ fail
4572fi
73+ STEP=" session-visit"
4674" $CLI " session create qa | grep -q ' "session":"qa"'
4775" $CLI " session list | grep -q ' "qa"'
4876" $CLI " --session qa visit " http://127.0.0.1:$PORT /designers/dashboard" | grep -q ' Designers Dashboard'
77+ STEP=" inspect-diagnostics"
4978SNAPSHOT=" $( " $CLI " --session qa inspect --interactive --text) "
5079echo " $SNAPSHOT " | grep -q ' "name":"Continue"'
5180echo " $SNAPSHOT " | grep -q ' "name":"Reviewer"'
@@ -69,40 +98,43 @@ echo "$STORAGE" | grep -q 'qa-diagnostic-key'
6998echo " $STORAGE " | grep -q ' qa-session-key'
7099if SENSITIVE_STORAGE=" $( " $CLI " --session qa storage list --values) " ; then
71100 echo " sensitive storage values were available without opt-in" >&2
72- exit 1
101+ fail
73102fi
74103echo " $SENSITIVE_STORAGE " | grep -q ' SENSITIVE_DIAGNOSTICS_DISABLED'
104+ STEP=" qa-report"
75105QA_REPORT=" $( " $CLI " --session qa qa report) "
76106echo " $QA_REPORT " | grep -q ' "kind":"console"'
77107echo " $QA_REPORT " | grep -q ' "status":404'
78108echo " $QA_REPORT " | grep -q ' "kind":"framework-error"'
79109echo " $QA_REPORT " | grep -q ' "kind":"local-not-found"'
80110" $CLI " --session qa qa clear | grep -q ' "cleared"'
81111" $CLI " --session qa qa report | grep -q ' "events":0'
112+ STEP=" safe-input-navigation"
82113" $CLI " --session qa fill @e1 ' Ada Lovelace' | grep -q ' "valueLength":12'
83114" $CLI " --session qa press Escape | grep -q ' "pressed":"Escape"'
84115if EXTERNAL_RESULT=" $( " $CLI " --session qa click --role link --name ' External application' ) " ; then
85116 echo " external application link was not blocked" >&2
86- exit 1
117+ fail
87118fi
88119echo " $EXTERNAL_RESULT " | grep -q ' UNSAFE_NAVIGATION'
89120if NON_WEB_RESULT=" $( " $CLI " --session qa click --role link --name ' Non-web browser URL' ) " ; then
90121 echo " non-HTTP browser URL was not blocked" >&2
91- exit 1
122+ fail
92123fi
93124echo " $NON_WEB_RESULT " | grep -q ' UNSAFE_NAVIGATION'
94125if CREDENTIAL_RESULT=" $( " $CLI " --session qa click --role link --name ' Credential-bearing URL' ) " ; then
95126 echo " credential-bearing browser URL was not blocked" >&2
96- exit 1
127+ fail
97128fi
98129echo " $CREDENTIAL_RESULT " | grep -q ' UNSAFE_NAVIGATION'
99130if SUSPICIOUS_RESULT=" $( " $CLI " --session qa click --role link --name ' Suspicious installer' ) " ; then
100131 echo " suspicious installer link was not blocked" >&2
101- exit 1
132+ fail
102133fi
103134echo " $SUSPICIOUS_RESULT " | grep -q ' UNSAFE_RESOURCE_TYPE'
104135" $CLI " --session qa click --role button --name ' Scripted non-web navigation' | grep -q ' "clicked"'
105136" $CLI " --session qa wait --url /designers/dashboard --settled --timeout 10000 | grep -q ' Designers Dashboard'
137+ STEP=" artifacts-visual"
106138" $CLI " --session qa screenshot --output viewport.png | grep -q ' "name":"viewport.png"'
107139" $CLI " --session qa screenshot --full-page --output full-page.png | grep -q ' "name":"full-page.png"'
108140" $CLI " --session qa screenshot --role button --name Continue --output continue.png | grep -q ' "name":"continue.png"'
@@ -112,11 +144,13 @@ test -s "$HEADLESS_ARTIFACT_DIR/visual-diff.png"
112144ANIMATIONS=" $( " $CLI " --session qa animations list) "
113145echo " $ANIMATIONS " | grep -q ' "animations"'
114146echo " $ANIMATIONS " | grep -q ' "iterations":null'
115- if NETWORK_SIMULATION=" $( $CLI --session qa network emulate --latency 25) " ; then
147+ STEP=" network-emulate-unsupported"
148+ if NETWORK_SIMULATION=" $( " $CLI " --session qa network emulate --latency 25) " ; then
116149 echo " WebKit network emulation was unexpectedly exposed" >&2
117- exit 1
150+ fail
118151fi
119152echo " $NETWORK_SIMULATION " | grep -q ' UNSUPPORTED_CAPABILITY'
153+ STEP=" flows-reports"
120154" $CLI " --session qa flow start | grep -q ' "recording":true'
121155" $CLI " --session qa visit " http://127.0.0.1:$PORT /designers/dashboard" | grep -q ' Designers Dashboard'
122156" $CLI " --session qa click --role button --name Continue | grep -q ' "clicked"'
@@ -133,17 +167,18 @@ FULL_HEIGHT="$(sips -g pixelHeight "$HEADLESS_ARTIFACT_DIR/full-page.png" | awk
133167test " $FULL_HEIGHT " -gt " $VIEWPORT_HEIGHT "
134168if " $CLI " --session qa screenshot --output viewport.png > /dev/null 2>&1 ; then
135169 echo " artifact overwrite was not rejected" >&2
136- exit 1
170+ fail
137171fi
138172if " $CLI " screenshot --output ../escape.png > /dev/null 2>&1 ; then
139173 echo " artifact path traversal was not rejected" >&2
140- exit 1
174+ fail
141175fi
176+ STEP=" recording"
142177" $CLI " --session qa record start --fps 5 | grep -q ' "active":true'
143178" $CLI " --session qa record status | grep -q ' "active":true'
144179if " $CLI " --session qa record start > /dev/null 2>&1 ; then
145180 echo " a second recording was not rejected" >&2
146- exit 1
181+ fail
147182fi
148183" $CLI " --session qa tour --full-page --pace 5000 | grep -q ' "durationMs"'
149184" $CLI " --session qa click --role button --name Continue | grep -q ' "clicked"'
@@ -157,6 +192,7 @@ test "$(stat -f %Lp "$HEADLESS_ARTIFACT_DIR/dashboard-flow.mp4")" = "600"
157192" $CLI " artifacts list | grep -q ' "name":"dashboard-flow.mp4"'
158193" $CLI " --session qa back | grep -q ' Designers Dashboard'
159194" $CLI " --session qa reload | grep -q ' Designers Dashboard'
195+ STEP=" capture-hostile"
160196CAPTURE=" $( " $CLI " --session qa capture-info) "
161197echo " $CAPTURE " | grep -q ' "engine":"webkit"'
162198echo " $CAPTURE " | grep -q ' "windowId"'
0 commit comments