Skip to content

Commit 2daa831

Browse files
committed
test: print form and heading summary on OAuth flow failure
When GitHub serves an unexpected page (e.g. a new 2FA re-verification variant we do not yet recognize), the test now prints the form actions, input names, and h1/h2 text in the failure message. Form values and body content are not emitted, so nothing sensitive lands in CI logs. Signed-off-by: Oleksander Piskun <oleksandr2088@icloud.com>
1 parent a7aca8c commit 2daa831

2 files changed

Lines changed: 46 additions & 1 deletion

File tree

tests/integration/GitHubHtml.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,45 @@ public static function extractFormInputs(DOMXPath $selector, DOMElement $form):
106106

107107
return $formParams;
108108
}
109+
110+
/**
111+
* Summarize the forms and headings on a page for failure diagnostics.
112+
* Emits form actions and input names (never values) plus h1/h2 text,
113+
* so CI logs show what GitHub actually returned without leaking tokens.
114+
*/
115+
public static function describePage(DOMXPath $selector): string {
116+
$parts = [];
117+
118+
$forms = $selector->query('//form');
119+
if ($forms !== false) {
120+
foreach ($forms as $form) {
121+
if (!$form instanceof DOMElement) {
122+
continue;
123+
}
124+
$action = $form->getAttribute('action');
125+
$inputNodes = $selector->query('.//input[@name] | .//button[@name]', $form);
126+
$names = [];
127+
if ($inputNodes !== false) {
128+
foreach ($inputNodes as $input) {
129+
if ($input instanceof DOMElement) {
130+
$names[] = $input->getAttribute('name');
131+
}
132+
}
133+
}
134+
$parts[] = 'form(action=' . ($action === '' ? '<empty>' : $action) . ', inputs=[' . implode(',', $names) . '])';
135+
}
136+
}
137+
138+
$headings = $selector->query('//h1 | //h2');
139+
if ($headings !== false) {
140+
foreach ($headings as $heading) {
141+
$text = trim($heading->textContent);
142+
if ($text !== '') {
143+
$parts[] = $heading->nodeName . '=' . mb_substr($text, 0, 120);
144+
}
145+
}
146+
}
147+
148+
return $parts === [] ? '<no forms or headings found>' : implode(' | ', $parts);
149+
}
109150
}

tests/integration/GithubOauthIntegrationTest.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,11 @@ private function interpretAuthenticatedResponse(string $body, string $finalUrl,
261261
$this->fail('GitHub returned the sign-in page after the ' . $step . ' step. This usually means the authenticated session was not established or cookies were not kept. Final URL: ' . $finalUrl);
262262
}
263263

264-
$this->fail('GitHub completed the ' . $step . ' step but neither a 2FA form, an authorize form, nor a callback redirect with code was found. Final URL: ' . $finalUrl . '. Page title: ' . $title);
264+
$this->fail(
265+
'GitHub completed the ' . $step . ' step but neither a 2FA form, an authorize form, nor a callback redirect with code was found. '
266+
. 'Final URL: ' . $finalUrl . '. Page title: ' . $title . '. '
267+
. 'Page: ' . GitHubHtml::describePage($selector)
268+
);
265269
}
266270

267271
private function loginToGitHub(string $authorizeUrl): array {

0 commit comments

Comments
 (0)