Summary
BrowserPage.goto() currently updates page.url but does not perform a request, parse the response body, replace the document, return the main-resource Response, or emit navigation lifecycle events.
That makes the Browser API example in the README look successful while leaving the previous/empty document in place. It also blocks the basic Playwright-style flow of navigating to a local app and interacting with the loaded page.
Reproduction
import { Browser } from 'very-happy-dom'
let fetchCalls = 0
globalThis.fetch = async () => {
fetchCalls++
return new Response('<h1>Loaded</h1>', {
headers: { 'content-type': 'text/html' },
})
}
const page = new Browser().newPage()
const response = await page.goto('https://example.test/demo')
console.log(fetchCalls) // 0
console.log(response) // null
console.log(page.url) // https://example.test/demo
console.log(page.mainFrame.document.querySelector('h1')) // nullConfirmed against main at 59d2e7c3 with Bun 1.4.1.
Current implementation
BrowserFrame.goto() only assigns this.url = url and returns null. waitForNavigation(), waitUntilComplete(), goBack(), goForward(), goSteps(), and reload() are also no-ops.
Expected behavior
At minimum, main-frame navigation should:
- Resolve and request the target URL.
- Populate a fresh document from an HTML response.
- Update
window.locationand history coherently. - Return the main-resource
Response(ornullfor non-network navigations). - Emit the supported
domcontentloadedandloadpage events in a deterministic order. - Make
waitForNavigation()/reload()observe the same navigation lifecycle.
Playwright's page.goto() loads the URL and returns the main-resource response: https://playwright.dev/docs/api/class-page#page-goto
If full script/resource loading is intentionally out of scope for the virtual DOM, loading and parsing the main HTML response would still make the documented Browser API usable and the limitation could be documented explicitly.
Why this matters
Without real main-resource navigation, Browser, BrowserContext, and BrowserPage cannot replace even lightweight Playwright browser tests: every caller must fetch HTML and inject page.content manually, navigation waits cannot be used, and redirects/history cannot be tested through the public API.