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

Commit 1d32ee4

Browse files
author
Ivan Mirić
committed
Add lifecycle event validation to WaitForLoadState
1 parent 97ef8a7 commit 1d32ee4

File tree

4 files changed

+136
-8
lines changed

4 files changed

+136
-8
lines changed

common/frame.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1583,12 +1583,9 @@ func (f *Frame) WaitForLoadState(state string, opts goja.Value) {
15831583
k6Throw(f.ctx, "cannot parse waitForLoadState options: %v", err)
15841584
}
15851585

1586-
waitUntil := LifecycleEventLoad
1587-
switch state {
1588-
case "domcontentloaded":
1589-
waitUntil = LifecycleEventDOMContentLoad
1590-
case "networkidle":
1591-
waitUntil = LifecycleEventNetworkIdle
1586+
var waitUntil LifecycleEvent
1587+
if err = waitUntil.UnmarshalText([]byte(state)); err != nil {
1588+
k6Throw(f.ctx, "waitForLoadState error: %v", err)
15921589
}
15931590

15941591
if f.hasLifecycleEventFired(waitUntil) {

common/types.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import (
2626
"encoding/json"
2727
"fmt"
2828
"math"
29+
"sort"
30+
"strings"
2931

3032
"github.com/dop251/goja"
3133

@@ -278,6 +280,47 @@ func (l *LifecycleEvent) UnmarshalJSON(b []byte) error {
278280
return nil
279281
}
280282

283+
// MarshalText returns the string representation of the enum value.
284+
// It returns an error if the enum value is invalid.
285+
func (l *LifecycleEvent) MarshalText() ([]byte, error) {
286+
if l == nil {
287+
return []byte(""), nil
288+
}
289+
var (
290+
ok bool
291+
s string
292+
)
293+
if s, ok = lifecycleEventToString[*l]; !ok {
294+
return nil, fmt.Errorf("invalid lifecycle event: %v", int(*l))
295+
}
296+
297+
return []byte(s), nil
298+
}
299+
300+
// UnmarshalText unmarshals a text representation to the enum value.
301+
// It returns an error if given a wrong value.
302+
func (l *LifecycleEvent) UnmarshalText(text []byte) error {
303+
var (
304+
ok bool
305+
val = string(text)
306+
)
307+
308+
if *l, ok = lifecycleEventToID[val]; !ok {
309+
valid := make([]string, 0, len(lifecycleEventToID))
310+
for k := range lifecycleEventToID {
311+
valid = append(valid, k)
312+
}
313+
sort.Slice(valid, func(i, j int) bool {
314+
return lifecycleEventToID[valid[j]] > lifecycleEventToID[valid[i]]
315+
})
316+
return fmt.Errorf(
317+
"invalid lifecycle event: %q; must be one of: %s",
318+
val, strings.Join(valid, ", "))
319+
}
320+
321+
return nil
322+
}
323+
281324
type MediaType string
282325

283326
const (

common/types_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"testing"
55

66
"github.com/stretchr/testify/assert"
7+
"github.com/stretchr/testify/require"
78
)
89

910
// See: Issue #183 for details.
@@ -60,3 +61,71 @@ func TestViewportCalculateInset(t *testing.T) {
6061
})
6162
}
6263
}
64+
65+
func TestLifecycleEventMarshalText(t *testing.T) {
66+
t.Parallel()
67+
68+
t.Run("ok/nil", func(t *testing.T) {
69+
t.Parallel()
70+
71+
var evt *LifecycleEvent
72+
m, err := evt.MarshalText()
73+
require.NoError(t, err)
74+
assert.Equal(t, []byte(""), m)
75+
})
76+
77+
t.Run("err/invalid", func(t *testing.T) {
78+
t.Parallel()
79+
80+
evt := LifecycleEvent(-1)
81+
_, err := evt.MarshalText()
82+
require.EqualError(t, err, "invalid lifecycle event: -1")
83+
})
84+
}
85+
86+
func TestLifecycleEventMarshalTextRound(t *testing.T) {
87+
t.Parallel()
88+
89+
evt := LifecycleEventLoad
90+
m, err := evt.MarshalText()
91+
require.NoError(t, err)
92+
assert.Equal(t, []byte("load"), m)
93+
94+
var evt2 LifecycleEvent
95+
err = evt2.UnmarshalText(m)
96+
require.NoError(t, err)
97+
assert.Equal(t, evt, evt2)
98+
}
99+
100+
func TestLifecycleEventUnmarshalText(t *testing.T) {
101+
t.Parallel()
102+
103+
t.Run("ok", func(t *testing.T) {
104+
t.Parallel()
105+
106+
var evt LifecycleEvent
107+
err := evt.UnmarshalText([]byte("load"))
108+
require.NoError(t, err)
109+
assert.Equal(t, LifecycleEventLoad, evt)
110+
})
111+
112+
t.Run("err/invalid", func(t *testing.T) {
113+
t.Parallel()
114+
115+
var evt LifecycleEvent
116+
err := evt.UnmarshalText([]byte("none"))
117+
require.EqualError(t, err,
118+
`invalid lifecycle event: "none"; `+
119+
`must be one of: load, domcontentloaded, networkidle`)
120+
})
121+
122+
t.Run("err/invalid_empty", func(t *testing.T) {
123+
t.Parallel()
124+
125+
var evt LifecycleEvent
126+
err := evt.UnmarshalText([]byte(""))
127+
require.EqualError(t, err,
128+
`invalid lifecycle event: ""; `+
129+
`must be one of: load, domcontentloaded, networkidle`)
130+
})
131+
}

tests/page_test.go

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,26 @@ func TestPageWaitForFunction(t *testing.T) {
629629
})
630630
}
631631

632+
func TestPageWaitForLoadState(t *testing.T) {
633+
t.Parallel()
634+
635+
// TODO: Add happy path tests once WaitForLoadState is not racy.
636+
637+
t.Run("err_wrong_event", func(t *testing.T) {
638+
t.Parallel()
639+
640+
defer func() {
641+
assertPanicErrorContains(t, recover(),
642+
`invalid lifecycle event: "none"; `+
643+
`must be one of: load, domcontentloaded, networkidle`)
644+
}()
645+
646+
p := newTestBrowser(t).NewPage(nil)
647+
p.WaitForLoadState("none", nil)
648+
t.Error("did not panic")
649+
})
650+
}
651+
632652
// See: The issue #187 for details.
633653
func TestPageWaitForNavigationShouldNotPanic(t *testing.T) {
634654
ctx, cancel := context.WithCancel(context.Background())
@@ -645,8 +665,7 @@ func assertPanicErrorContains(t *testing.T, err interface{}, expErrMsg string) {
645665
require.IsType(t, &goja.Object{}, err)
646666
gotObj, _ := err.(*goja.Object)
647667
got := gotObj.Export()
648-
expErr := fmt.Errorf("%w", errors.New(expErrMsg))
649-
require.IsType(t, expErr, got)
668+
expErr := errors.New(expErrMsg)
650669
gotErr, ok := got.(error)
651670
require.True(t, ok)
652671
assert.Contains(t, gotErr.Error(), expErr.Error())

0 commit comments

Comments
 (0)