Skip to content
This repository has been archived by the owner on Jan 30, 2025. It is now read-only.

Commit

Permalink
Fix WaitUntil for long running network requests
Browse files Browse the repository at this point in the history
Some websites may have many network requests which are performed after
the page has fully loaded and we receive a FrameStoppedLoading. For
now we want to wait for the networkIdle event, and in the future if we
need, we should add a timer for very chatty websites where we may
never see a networkIdle event.

Partly fixes: https://github.com/orgs/grafana/projects/80/views/14
  • Loading branch information
ankur22 committed Oct 19, 2022
1 parent d4c6087 commit f5158dd
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 8 deletions.
16 changes: 10 additions & 6 deletions common/frame.go
Original file line number Diff line number Diff line change
Expand Up @@ -458,12 +458,16 @@ func (f *Frame) onLoadingStarted() {
func (f *Frame) onLoadingStopped() {
f.log.Debugf("Frame:onLoadingStopped", "fid:%s furl:%q", f.ID(), f.URL())

f.lifecycleEventsMu.Lock()
defer f.lifecycleEventsMu.Unlock()

f.lifecycleEvents[LifecycleEventDOMContentLoad] = true
f.lifecycleEvents[LifecycleEventLoad] = true
f.lifecycleEvents[LifecycleEventNetworkIdle] = true
// TODO: We should start a timer here and allow the user
// to set how long to wait until after onLoadingStopped
// has occurred. The reason we may want a timeout here
// are for websites where they perform many network
// requests so it may take a long time for us to see
// a networkIdle event or we may never see one if the
// website never stops performing network requests.
// NOTE: This is a different timeout to networkIdleTimer,
// which only works once there are no more network
// requests and we don't see a networkIdle event.
}

func (f *Frame) position() *Position {
Expand Down
4 changes: 2 additions & 2 deletions common/frame_session.go
Original file line number Diff line number Diff line change
Expand Up @@ -475,8 +475,8 @@ func (fs *FrameSession) handleFrameTree(frameTree *cdppage.FrameTree) {

func (fs *FrameSession) navigateFrame(frame *Frame, url, referrer string) (string, error) {
fs.logger.Debugf("FrameSession:navigateFrame",
"sid:%v tid:%v url:%q referrer:%q",
fs.session.ID(), fs.targetID, url, referrer)
"sid:%v fid:%s tid:%v url:%q referrer:%q",
fs.session.ID(), frame.ID(), fs.targetID, url, referrer)

action := cdppage.Navigate(url).WithReferrer(referrer).WithFrameID(cdp.FrameID(frame.ID()))
_, documentID, errorText, err := action.Do(cdp.WithExecutor(fs.ctx, fs.session))
Expand Down
74 changes: 74 additions & 0 deletions tests/frame_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,4 +172,78 @@ func TestLifecycleNetworkIdle(t *testing.T) {
assert.True(t, resolved)
assert.False(t, rejected)
})

t.Run("doesn't unblock wait on networkIdle early when load and domcontentloaded complete at once", func(t *testing.T) {
t.Parallel()

tb := newTestBrowser(t, withHTTPServer())
p := tb.NewPage(nil)

counterMu := sync.RWMutex{}
var counter int

tb.withHandler("/home", func(w http.ResponseWriter, _ *http.Request) {
fmt.Fprintf(w, `
<html>
<head></head>
<body>
<div id="prolongNetworkIdleLoad">Waiting...</div>
<script>
var prolongNetworkIdleLoadOutput = document.getElementById("prolongNetworkIdleLoad");
var p = prolongNetworkIdleLoad();
p.then(() => {
prolongNetworkIdleLoadOutput.innerText += ' - for loop complete';
})
async function prolongNetworkIdleLoad() {
for (var i = 0; i < 10; i++) {
await fetch('/ping')
.then(response => response.text())
.then((data) => {
prolongNetworkIdleLoadOutput.innerText = 'Waiting... ' + data;
});
}
}
</script>
</body>
</html>
`)
})
tb.withHandler("/ping", func(w http.ResponseWriter, _ *http.Request) {
counterMu.Lock()
defer counterMu.Unlock()

time.Sleep(time.Millisecond * 50)

counter++
fmt.Fprintf(w, "pong %d", counter)
})

var resolved, rejected bool
err := tb.await(func() error {
opts := tb.toGojaValue(common.FrameGotoOptions{
WaitUntil: common.LifecycleEventNetworkIdle,
Timeout: 30 * time.Second,
})
tb.promise(p.Goto(tb.URL("/home"), opts)).then(
func() {
result := p.TextContent("#prolongNetworkIdleLoad", nil)
assert.EqualValues(t, "Waiting... pong 10 - for loop complete", result)

resolved = true
},
func() {
rejected = true
},
)

return nil
})
require.NoError(t, err)

assert.True(t, resolved)
assert.False(t, rejected)
})
}

0 comments on commit f5158dd

Please sign in to comment.