diff --git a/fixtures/page-wait-stable.html b/fixtures/page-wait-stable.html index b36a2172..3f1e76c6 100644 --- a/fixtures/page-wait-stable.html +++ b/fixtures/page-wait-stable.html @@ -1,89 +1,19 @@ - - PageWaitStable - - - - - - - -
- loading -
- - - - - +
diff --git a/must.go b/must.go index be9e6907..81a77adc 100644 --- a/must.go +++ b/must.go @@ -416,7 +416,11 @@ func (p *Page) MustWaitNavigation() func() { // MustWaitRequestIdle is similar to Page.WaitRequestIdle func (p *Page) MustWaitRequestIdle(excludes ...string) (wait func()) { - return p.WaitRequestIdle(300*time.Millisecond, nil, excludes) + return p.WaitRequestIdle(300*time.Millisecond, nil, excludes, []proto.NetworkResourceType{ + proto.NetworkResourceTypeWebSocket, + proto.NetworkResourceTypeEventSource, + proto.NetworkResourceTypeMedia, + }) } // MustWaitIdle is similar to Page.WaitIdle @@ -427,7 +431,7 @@ func (p *Page) MustWaitIdle() *Page { // MustWaitStable is similar to Page.WaitStable func (p *Page) MustWaitStable() *Page { - p.e(p.WaitStable(800*time.Millisecond, 1)) + p.e(p.WaitStable(500*time.Millisecond, 0)) return p } diff --git a/page.go b/page.go index 0a167e82..e5ca7846 100644 --- a/page.go +++ b/page.go @@ -584,7 +584,9 @@ func (p *Page) WaitNavigation(name proto.PageLifecycleEventName) func() { // Be careful, d is not the max wait timeout, it's the least idle time. // If you want to set a timeout you can use the "Page.Timeout" function. // Use the includes and excludes regexp list to filter the requests by their url. -func (p *Page) WaitRequestIdle(d time.Duration, includes, excludes []string) func() { +func (p *Page) WaitRequestIdle(d time.Duration, includes, excludes []string, excludeTypes []proto.NetworkResourceType) func() { + defer p.tryTrace(TraceTypeWait, "request-idle")() + if len(includes) == 0 { includes = []string{""} } @@ -605,6 +607,12 @@ func (p *Page) WaitRequestIdle(d time.Duration, includes, excludes []string) fun } wait := p.EachEvent(func(sent *proto.NetworkRequestWillBeSent) { + for _, t := range excludeTypes { + if sent.Type == t { + return + } + } + if match(sent.Request.URL) { // Redirect will send multiple NetworkRequestWillBeSent events with the same RequestID, // we should filter them out. @@ -629,13 +637,18 @@ func (p *Page) WaitRequestIdle(d time.Duration, includes, excludes []string) fun } } -// WaitStable like "Element.WaitStable". WaitStable polling the changes -// of the DOM tree in `d` duration,until the similarity equal or more than simThreshold. -// `simThreshold` is the similarity threshold,it's scope in [0,1]. -// Be careful,d is not the max wait timeout, it's the least stable time. +// WaitStable waits until the change of the DOM tree is less or equal than diff percent for d duration. +// Be careful, d is not the max wait timeout, it's the least stable time. // If you want to set a timeout you can use the "Page.Timeout" function. -func (p *Page) WaitStable(d time.Duration, similarity float32) error { - defer p.tryTrace(TraceTypeWait, "stable") +func (p *Page) WaitStable(d time.Duration, diff float64) error { + defer p.tryTrace(TraceTypeWait, "stable")() + + err := p.WaitLoad() + if err != nil { + return err + } + + p.MustWaitRequestIdle()() domSnapshot, err := p.CaptureDOMSnapshot() if err != nil { @@ -659,10 +672,10 @@ func (p *Page) WaitStable(d time.Duration, similarity float32) error { xs := lcs.NewWords(domSnapshot.Strings) ys := lcs.NewWords(currentDomSnapshot.Strings) - diff := xs.YadLCS(p.ctx, ys) + lcs := xs.YadLCS(p.ctx, ys) - sim := float32(len(diff)) / float32(len(ys)) - if sim >= similarity { + df := 1 - float64(len(lcs))/float64(len(ys)) + if df <= diff { break } diff --git a/page_test.go b/page_test.go index 4bb02f69..40f2f15d 100644 --- a/page_test.go +++ b/page_test.go @@ -525,14 +525,24 @@ func TestPageCaptureDOMSnapshot(t *testing.T) { func TestPageWaitStable(t *testing.T) { g := setup(t) - p := g.page.MustNavigate(g.srcFile("fixtures/page-wait-stable.html")) - // wait for p loading and rending complete - p.MustWaitStable() + { + p := g.page.MustNavigate(g.srcFile("fixtures/page-wait-stable.html")) + p.MustWaitStable() + } - // for waitStable timeout - timeOutPage := p.Timeout(1 * time.Second) - err := timeOutPage.WaitStable(2*time.Second, 1) - g.Is(err, context.DeadlineExceeded) + { + p := g.page.MustNavigate(g.srcFile("fixtures/page-wait-stable.html")) + err := p.Timeout(time.Second).WaitStable(time.Second, 0) + g.Is(err, context.DeadlineExceeded) + } + + { + g.Panic(func() { + p := g.page.MustWaitStable() + g.mc.stubErr(1, proto.RuntimeCallFunctionOn{}) + p.MustWaitStable() + }) + } { g.Panic(func() {