Skip to content

Commit 5c07be6

Browse files
committed
feat(scaletest/dashboard): remove unused code
1 parent 0ae372d commit 5c07be6

File tree

7 files changed

+105
-484
lines changed

7 files changed

+105
-484
lines changed

cli/exp_scaletest.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1122,7 +1122,8 @@ func (r *RootCmd) scaletestDashboard() *clibase.Cmd {
11221122
Headless: headless,
11231123
ActionFunc: dashboard.ClickRandomElement,
11241124
}
1125-
logger.Info(ctx, "runner config", slog.F("min_wait", minWait), slog.F("max_wait", maxWait), slog.F("headless", headless))
1125+
//nolint:gocritic
1126+
logger.Info(ctx, "runner config", slog.F("min_wait", minWait), slog.F("max_wait", maxWait), slog.F("headless", headless), slog.F("trace", tracingEnabled))
11261127
if err := config.Validate(); err != nil {
11271128
return err
11281129
}

scaletest/dashboard/cache.go

Lines changed: 0 additions & 97 deletions
This file was deleted.

scaletest/dashboard/chromedp.go

Lines changed: 98 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package dashboard
22

33
import (
44
"context"
5+
"math/rand"
56
"net/url"
67
"os"
78
"time"
@@ -18,56 +19,106 @@ type Action func(ctx context.Context) error
1819
// Selector locates an element on a page.
1920
type Selector string
2021

22+
// Target is a thing that can be clicked.
23+
type Target struct {
24+
// Label is a human-readable label for the target.
25+
Label Label
26+
// ClickOn is the selector that locates the element to be clicked.
27+
ClickOn Selector
28+
// WaitFor is a selector that is expected to appear after the target is clicked.
29+
WaitFor Selector
30+
}
31+
2132
// Label identifies an action.
2233
type Label string
2334

24-
// defaultSelectors is a map of labels to selectors.
25-
var defaultSelectors = map[Label]Selector{
26-
"workspaces_list": `nav a[href="/workspaces"]:not(.active)`,
27-
"templates_list": `nav a[href="/templates"]:not(.active)`,
28-
"users_list": `nav a[href^="/users"]:not(.active)`,
29-
"deployment_status": `nav a[href="/deployment/general"]:not(.active)`,
30-
"starter_templates": `a[href="/starter-templates"]`,
31-
"workspaces_table_row": `tr[role="button"][data-testid^="workspace-"]`,
32-
"workspace_builds_table_row": `tr[role="button"][data-testid^="build-"]`,
33-
"templates_table_row": `tr[role="button"][data-testid^="template-"]`,
34-
"template_docs": `a[href^="/templates/"][href$="/docs"]:not([aria-current])`,
35-
"template_files": `a[href^="/templates/"][href$="/files"]:not([aria-current])`,
36-
"template_versions": `a[href^="/templates/"][href$="/versions"]:not([aria-current])`,
37-
"template_embed": `a[href^="/templates/"][href$="/embed"]:not([aria-current])`,
38-
"template_insights": `a[href^="/templates/"][href$="/insights"]:not([aria-current])`,
35+
var defaultTargets = []Target{
36+
{
37+
Label: "workspace_list",
38+
ClickOn: `nav a[href="/workspaces"]:not(.active)`,
39+
WaitFor: `tr[role="button"][data-testid^="workspace-"]`,
40+
},
41+
{
42+
Label: "starter_templates",
43+
ClickOn: `a[href="/starter-templates"]`,
44+
WaitFor: `a[href^="/starter-templates/"]`,
45+
},
46+
{
47+
Label: "workspace_details",
48+
ClickOn: `tr[role="button"][data-testid^="workspace-"]`,
49+
WaitFor: `tr[role="button"][data-testid^="build-"]`,
50+
},
51+
{
52+
Label: "workspace_build_details",
53+
ClickOn: `tr[role="button"][data-testid^="build-"]`,
54+
WaitFor: `*[aria-label="Build details"]`,
55+
},
56+
{
57+
Label: "template_list",
58+
ClickOn: `nav a[href="/templates"]:not(.active)`,
59+
WaitFor: `tr[role="button"][data-testid^="template-"]`,
60+
},
61+
{
62+
Label: "template_docs",
63+
ClickOn: `a[href^="/templates/"][href$="/docs"]:not([aria-current])`,
64+
WaitFor: `#readme`,
65+
},
66+
{
67+
Label: "template_files",
68+
ClickOn: `a[href^="/templates/"][href$="/docs"]:not([aria-current])`,
69+
WaitFor: `.monaco-editor`,
70+
},
71+
{
72+
Label: "template_versions",
73+
ClickOn: `a[href^="/templates/"][href$="/versions"]:not([aria-current])`,
74+
WaitFor: `tr[role="button"][data-testid^="version-"]`,
75+
},
76+
{
77+
Label: "template_version_details",
78+
ClickOn: `tr[role="button"][data-testid^="version-"]`,
79+
WaitFor: `.monaco-editor`,
80+
},
81+
{
82+
Label: "user_list",
83+
ClickOn: `nav a[href^="/users"]:not(.active)`,
84+
WaitFor: `tr[data-testid^="user-"]`,
85+
},
3986
}
4087

41-
// ClickRandomElement returns an action that will click an element from the given selectors at random.
88+
// ClickRandomElement returns an action that will click an element from defaultTargets.
4289
// If no elements are found, an error is returned.
4390
// If more than one element is found, one is chosen at random.
4491
// The label of the clicked element is returned.
4592
func ClickRandomElement(ctx context.Context) (Label, Action, error) {
46-
var matched Selector
47-
var matchedLabel Label
93+
var xpath Selector
4894
var found bool
4995
var err error
50-
for l, s := range defaultSelectors {
51-
matched, found, err = randMatch(ctx, s)
96+
matches := make(map[Label]Selector)
97+
waitFor := make(map[Label]Selector)
98+
for _, tgt := range defaultTargets {
99+
xpath, found, err = randMatch(ctx, tgt.ClickOn)
52100
if err != nil {
53-
return "", nil, xerrors.Errorf("find matches for %q: %w", s, err)
101+
return "", nil, xerrors.Errorf("find matches for %q: %w", tgt.ClickOn, err)
54102
}
55103
if !found {
56104
continue
57105
}
58-
matchedLabel = l
59-
break
60-
}
61-
if !found {
62-
return "", nil, xerrors.Errorf("no matches found")
106+
matches[tgt.Label] = xpath
107+
waitFor[tgt.Label] = tgt.WaitFor
63108
}
64109

65-
return "click_" + matchedLabel, func(ctx context.Context) error {
66-
if err := clickAndWait(ctx, matched); err != nil {
67-
return xerrors.Errorf("click %q: %w", matched, err)
110+
// rely on map iteration order being random
111+
for lbl, tgt := range matches {
112+
act := func(actx context.Context) error {
113+
if err := clickAndWait(actx, tgt, waitFor[lbl]); err != nil {
114+
return xerrors.Errorf("click %q: %w", tgt, err)
115+
}
116+
return nil
68117
}
69-
return nil
70-
}, nil
118+
return lbl, act, nil
119+
}
120+
121+
return "", nil, xerrors.Errorf("no matches found")
71122
}
72123

73124
// randMatch returns a random match for the given selector.
@@ -89,25 +140,18 @@ func randMatch(ctx context.Context, s Selector) (Selector, bool, error) {
89140

90141
// clickAndWait clicks the given selector and waits for the page to finish loading.
91142
// The page is considered loaded when the network event "LoadingFinished" is received.
92-
func clickAndWait(ctx context.Context, s Selector) error {
143+
func clickAndWait(ctx context.Context, clickOn, waitFor Selector) error {
93144
return chromedp.Run(ctx, chromedp.Tasks{
94-
chromedp.Click(s, chromedp.NodeVisible),
95-
chromedp.ActionFunc(func(ctx context.Context) error {
96-
return waitForEvent(ctx, func(e interface{}) bool {
97-
if _, ok := e.(*network.EventLoadingFinished); ok {
98-
return true
99-
}
100-
return false
101-
})
102-
}),
145+
chromedp.Click(clickOn, chromedp.NodeVisible),
146+
chromedp.WaitVisible(waitFor, chromedp.NodeVisible),
103147
})
104148
}
105149

106150
// initChromeDPCtx initializes a chromedp context with the given session token cookie
107151
//
108152
//nolint:revive // yes, headless is a control flag
109153
func initChromeDPCtx(ctx context.Context, u *url.URL, sessionToken string, headless bool) (context.Context, context.CancelFunc, error) {
110-
dir, err := os.MkdirTemp("", "scaletest-dashboard")
154+
dir, err := os.MkdirTemp("", "scaletest-dashboard-*")
111155
if err != nil {
112156
return nil, nil, err
113157
}
@@ -145,7 +189,7 @@ func initChromeDPCtx(ctx context.Context, u *url.URL, sessionToken string, headl
145189
}
146190

147191
func setSessionTokenCookie(ctx context.Context, token, domain string) error {
148-
exp := cdp.TimeSinceEpoch(time.Now().Add(30 * 24 * time.Hour))
192+
exp := cdp.TimeSinceEpoch(time.Now().Add(24 * time.Hour))
149193
err := chromedp.Run(ctx, network.SetCookie("coder_session_token", token).
150194
WithExpires(&exp).
151195
WithDomain(domain).
@@ -156,26 +200,17 @@ func setSessionTokenCookie(ctx context.Context, token, domain string) error {
156200
return nil
157201
}
158202

159-
// waitForEvent waits for a lifecycle event that matches the given function.
160-
// Adapted from https://github.com/chromedp/chromedp/issues/431
161-
func waitForEvent(ctx context.Context, matcher func(e interface{}) bool) error {
162-
ch := make(chan struct{})
163-
cctx, cancel := context.WithCancel(ctx)
164-
defer cancel()
165-
chromedp.ListenTarget(cctx, func(evt interface{}) {
166-
if matcher(evt) {
167-
cancel()
168-
close(ch)
169-
}
170-
})
171-
select {
172-
case <-ch:
173-
return nil
174-
case <-ctx.Done():
175-
return ctx.Err()
176-
}
177-
}
178-
179203
func visitMainPage(ctx context.Context, u *url.URL) error {
180204
return chromedp.Run(ctx, chromedp.Navigate(u.String()))
181205
}
206+
207+
// pick chooses a random element from a slice.
208+
// If the slice is empty, it returns the zero value of the type.
209+
func pick[T any](s []T) T {
210+
if len(s) == 0 {
211+
var zero T
212+
return zero
213+
}
214+
// nolint:gosec
215+
return s[rand.Intn(len(s))]
216+
}

0 commit comments

Comments
 (0)