package webkit
import (
"context"
"net/url"
"testing"
"github.com/bnema/dumber/assets"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestCrashOriginalURI(t *testing.T) {
assert.Equal(t, "https://example.com/path?q=1", crashOriginalURI("dumb://home/crash?url=https%3A%2F%2Fexample.com%2Fpath%3Fq%3D1"))
assert.Empty(t, crashOriginalURI("dumb://home/crash"))
assert.Empty(t, crashOriginalURI("%%%"))
}
func TestBuildCrashPageHTMLIncludesReloadTarget(t *testing.T) {
body := buildCrashPageHTML("https://example.com/foo?a=1&b=2")
assert.Contains(t, body, `data-target="https://example.com/foo?a=1&b=2"`)
assert.Contains(t, body, "https://example.com/foo?a=1&b=2")
}
func TestBuildCrashPageHTMLFallbackReloadWithoutTarget(t *testing.T) {
body := buildCrashPageHTML("")
assert.Contains(t, body, "window.location.reload();")
}
func TestBuildCrashPageHTMLRejectsUnsafeReloadScheme(t *testing.T) {
// buildCrashPageHTML receives already-sanitized input from the caller.
// sanitizeCrashPageOriginalURI strips unsafe schemes to "".
sanitized := sanitizeCrashPageOriginalURI("javascript:alert(1)")
assert.Empty(t, sanitized)
body := buildCrashPageHTML(sanitized)
assert.Contains(t, body, `data-target=""`)
}
func TestBuildCrashPageHTMLAllowsDumbSchemeTarget(t *testing.T) {
body := buildCrashPageHTML("dumb://home")
assert.Contains(t, body, `data-target="dumb://home"`)
}
func TestBuildCrashPageHTMLEscapesScriptBreakoutPayload(t *testing.T) {
payload := `https://example.com/?q=`
body := buildCrashPageHTML(payload)
assert.NotContains(t, body, "")
assert.Contains(t, body, "</script><script>alert(1)</script>")
}
func TestRegisterDefaultsIncludesCrashHandler(t *testing.T) {
handler := NewDumbSchemeHandler(context.Background())
require.NotNil(t, handler)
handler.mu.RLock()
crashHandler, ok := handler.handlers["/crash"]
handler.mu.RUnlock()
require.True(t, ok)
require.NotNil(t, crashHandler)
resp := crashHandler.Handle(&SchemeRequest{
URI: "dumb://home/crash?url=https%3A%2F%2Fexample.com",
Path: "/crash",
Method: "GET",
Scheme: "dumb",
})
require.NotNil(t, resp)
assert.Equal(t, 200, resp.StatusCode)
assert.Equal(t, "text/html; charset=utf-8", resp.ContentType)
assert.Contains(t, string(resp.Data), "Renderer process ended")
}
func TestCrashHandlerSanitizesUnsafeURLQuery(t *testing.T) {
handler := NewDumbSchemeHandler(context.Background())
require.NotNil(t, handler)
handler.mu.RLock()
crashHandler, ok := handler.handlers["/crash"]
handler.mu.RUnlock()
require.True(t, ok)
require.NotNil(t, crashHandler)
resp := crashHandler.Handle(&SchemeRequest{
URI: "dumb://home/crash?url=javascript%3Aalert(1)",
Path: "/crash",
Method: "GET",
Scheme: "dumb",
})
require.NotNil(t, resp)
assert.Contains(t, string(resp.Data), `data-target=""`)
}
func TestHandleAsset_WebRTCRootServesInternalWebRTCTester(t *testing.T) {
h := NewDumbSchemeHandler(context.Background())
h.SetAssets(assets.WebUIAssets)
u, err := url.Parse("dumb://webrtc/")
require.NoError(t, err)
resp := h.handleAsset(u)
require.NotNil(t, resp)
assert.Equal(t, "text/html; charset=utf-8", resp.ContentType)
assert.Contains(t, string(resp.Data), "webrtc.min.js")
}
func TestHandleAsset_WebRTCOpaqueFormServesInternalWebRTCTester(t *testing.T) {
h := NewDumbSchemeHandler(context.Background())
h.SetAssets(assets.WebUIAssets)
u, err := url.Parse("dumb:webrtc")
require.NoError(t, err)
resp := h.handleAsset(u)
require.NotNil(t, resp)
assert.Equal(t, "text/html; charset=utf-8", resp.ContentType)
assert.Contains(t, string(resp.Data), "webrtc.min.js")
}
func TestHandleAsset_ConfigOpaqueFormServesConfigPage(t *testing.T) {
h := NewDumbSchemeHandler(context.Background())
h.SetAssets(assets.WebUIAssets)
u, err := url.Parse("dumb:config")
require.NoError(t, err)
resp := h.handleAsset(u)
require.NotNil(t, resp)
assert.Equal(t, "text/html; charset=utf-8", resp.ContentType)
assert.Contains(t, string(resp.Data), "config")
}