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
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
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() {