package web
import (
"strings"
"testing"
)
// The reporter speaks for THIS site's assets and nothing else.
//
// Every resource quarry references is same-origin by construction — the
// privacy page states it as a promise. So a cross-origin resource error
// is never quarry's asset failing; it is something else putting a URL on
// the page. On zeitforge that was Cloudflare injecting an analytics
// beacon the site never asked for, refused by the site's own CSP: 610
// journalled "exceptions" for a tracker failing to load, at six an hour,
// crowding out the faults that were real.
func TestTheReporterOnlySpeaksForOurOwnAssets(t *testing.T) {
js := string(onerrorJS)
if !strings.Contains(js, "function ours(url)") {
t.Fatal("FAIL: the reporter has no same-origin guard")
}
if !strings.Contains(js, "if (!ours(url)) return;") {
t.Error("FAIL: the resource branch does not consult the guard")
}
if !strings.Contains(js, "u.origin === location.origin") {
t.Error("FAIL: the guard does not compare origins")
}
// data: and blob: have an opaque origin matching nothing, but only
// our own markup can produce one, so those stay reportable.
if !strings.Contains(js, `u.protocol === "data:"`) {
t.Error("FAIL: a failed inline asset would be silently dropped")
}
// An unparseable URL must fall toward reporting: our own URLs always
// parse, and a false silence costs a broken asset nobody hears about.
if !strings.Contains(js, "} catch (e) {\n return true;") {
t.Error("FAIL: an unparseable URL does not fall toward reporting")
}
}
// The guard must not have swallowed the window-level error path: a
// thrown exception has no URL to be same-origin about.
func TestThrownErrorsAreStillReportedWhereverTheyCameFrom(t *testing.T) {
js := string(onerrorJS)
i := strings.Index(js, "if (!ours(url)) return;")
j := strings.Index(js, `post("error",`)
if i < 0 || j < 0 {
t.Fatal("FAIL: expected both the resource guard and the thrown-error path")
}
if j < i {
t.Fatal("FAIL: the thrown-error path moved above the resource branch")
}
// The thrown-error post must not be inside the guarded branch.
between := js[i:j]
if strings.Count(between, "return;") < 1 {
t.Error("FAIL: the resource branch no longer returns before the thrown-error path")
}
}