Skip to content

Commit f67a1a3

Browse files
authored
test: adapt UI e2e tests to prod environment (#1271)
* test: adapt ui e2e tests to prod environment * doc * doc improvement * improvements * requested changes * improvements * improvements * clean ksctl * improvement
1 parent 65b52a8 commit f67a1a3

8 files changed

Lines changed: 198 additions & 57 deletions

File tree

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
SSO_USERNAME=${SSO_USERNAME}
22
SSO_PASSWORD=${SSO_PASSWORD}
33
BASE_URL=${BASE_URL}
4-
ENVIRONMENT=ui-e2e-tests
5-
BROWSER=${BROWSER}
4+
ENVIRONMENT=${ENVIRONMENT}
5+
BROWSER=${BROWSER}
6+
KUBECONFIG=${KUBECONFIG}

make/devsandbox-dashboard.mk

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ e2e-run-devsandbox-dashboard:
4141
@echo "Running Developer Sandbox Dashboard setup e2e tests..."
4242
DEVSANDBOX_DASHBOARD_NS=${DEVSANDBOX_DASHBOARD_NS} go test "./test/e2e/devsandbox-dashboard/setup" -v -timeout=10m -failfast
4343

44-
@echo "Running Developer Sandbox Dashboard e2e tests in firefox..."
45-
@SSO_USERNAME=$(SSO_USERNAME_READ) SSO_PASSWORD=$(SSO_PASSWORD_READ) BASE_URL=${RHDH} BROWSER=firefox envsubst < deploy/devsandbox-dashboard/ui-e2e-tests/.env > testsupport/devsandbox-dashboard/.env
44+
@echo "Running Developer Sandbox Dashboard e2e tests in Firefox..."
45+
@SSO_USERNAME=$(SSO_USERNAME_READ) SSO_PASSWORD=$(SSO_PASSWORD_READ) BASE_URL=${RHDH} BROWSER=firefox ENVIRONMENT=${UI_ENVIRONMENT} envsubst < deploy/devsandbox-dashboard/ui-e2e-tests/.env > testsupport/devsandbox-dashboard/.env
4646
@HOST_NS=$(HOST_NS) MEMBER_NS=$(MEMBER_NS) MEMBER_NS_2=$(MEMBER_NS_2) REGISTRATION_SERVICE_NS=$(HOST_NS) SECOND_MEMBER_MODE=$(SECOND_MEMBER) go test "./test/e2e/devsandbox-dashboard" -v -timeout=10m -failfast
4747

4848
@echo "The Developer Sandbox Dashboard e2e tests successfully finished"
@@ -99,3 +99,32 @@ endif
9999
-e PUBLISH_UI=false \
100100
-e RUNNING_IN_CONTAINER=true \
101101
$(E2E_TEST_IMAGE_NAME) make test-devsandbox-dashboard-e2e
102+
103+
# Run Developer Sandbox Dashboard e2e tests against prod
104+
.PHONY: test-devsandbox-dashboard-e2e-prod
105+
test-devsandbox-dashboard-e2e-prod:
106+
@echo "Installing Firefox browser for Playwright..."
107+
go tool playwright install firefox
108+
109+
@echo "Running Developer Sandbox Dashboard e2e tests in Firefox..."
110+
@SSO_USERNAME=${SSO_USERNAME_READ} SSO_PASSWORD=${SSO_PASSWORD_READ} BASE_URL=https://sandbox.redhat.com/ BROWSER=firefox ENVIRONMENT=prod KUBECONFIG=${KUBECONFIG} envsubst < deploy/devsandbox-dashboard/ui-e2e-tests/.env > testsupport/devsandbox-dashboard/.env
111+
@go test "./test/e2e/devsandbox-dashboard" -v -timeout=10m -failfast
112+
113+
@echo "The Developer Sandbox Dashboard e2e tests successfully finished"
114+
115+
116+
# Run Developer Sandbox Dashboard e2e tests against prod in container using podman
117+
.PHONY: test-devsandbox-dashboard-in-container-prod
118+
test-devsandbox-dashboard-in-container-prod: build-devsandbox-dashboard-e2e-tests
119+
@rm -f build/_output/bin/ksctl
120+
@echo "running the prod e2e tests in podman container..."
121+
podman run --platform $(IMAGE_PLATFORM) --rm \
122+
-v $(KUBECONFIG):/root/.kube/config \
123+
-e KUBECONFIG=/root/.kube/config \
124+
-v ${PWD}:/root/toolchain-e2e \
125+
-e E2E_REPO_PATH=/root/toolchain-e2e \
126+
-e SSO_USERNAME=$(SSO_USERNAME) \
127+
-e SSO_PASSWORD=$(SSO_PASSWORD) \
128+
-e RUNNING_IN_CONTAINER=true \
129+
-e PATH=/app/build/_output/bin:$$PATH \
130+
$(E2E_TEST_IMAGE_NAME) make test-devsandbox-dashboard-e2e-prod

test/e2e/devsandbox-dashboard/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ If you want to use your local devsandbox-dashboard, please:
2929
1. Set the `QUAY_NAMESPACE` environment variable to your quay username: `export QUAY_NAMESPACE=<your-quay-username>`
3030
2. Run `make test-devsandbox-dashboard-in-container SSO_USERNAME=<SSO_USERNAME> SSO_PASSWORD=<SSO_PASSWORD> UI_REPO_PATH=${PWD}/../devsandbox-dashboard`
3131

32+
## Deploy Developer Sandbox Dashboard in Prod
33+
34+
`make test-devsandbox-dashboard-e2e-prod SSO_USERNAME=${SSO_USERNAME} SSO_PASSWORD=${SSO_PASSWORD} KUBECONFIG=${KUBECONFIG}`
35+
36+
`make test-devsandbox-dashboard-in-container-prod SSO_USERNAME=${SSO_USERNAME} SSO_PASSWORD=${SSO_PASSWORD} KUBECONFIG=${KUBECONFIG}`
37+
38+
The Developer Sandbox Dashboard E2E tests will run against the production environment at `https://sandbox.redhat.com/`.
39+
40+
3241
## Deploy Developer Sandbox Dashboard in E2E mode
3342

3443
Please note that OCP cluster does not have a valid CA, so when accessing the Developer Sandbox Dashboard, you need to:

test/e2e/devsandbox-dashboard/fresh_signup_test.go

Lines changed: 80 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@ import (
44
"context"
55
"errors"
66
"regexp"
7+
"strings"
78
"testing"
89

10+
toolchainv1alpha1 "github.com/codeready-toolchain/api/api/v1alpha1"
911
"github.com/codeready-toolchain/toolchain-e2e/testsupport"
10-
"github.com/codeready-toolchain/toolchain-e2e/testsupport/cleanup"
1112
sandboxui "github.com/codeready-toolchain/toolchain-e2e/testsupport/devsandbox-dashboard"
1213
"github.com/playwright-community/playwright-go"
1314
"github.com/spf13/viper"
1415
"github.com/stretchr/testify/assert"
1516
"github.com/stretchr/testify/require"
17+
"k8s.io/apimachinery/pkg/runtime"
18+
"k8s.io/client-go/tools/clientcmd"
19+
"sigs.k8s.io/controller-runtime/pkg/client"
1620
)
1721

1822
// TestFreshSignup tests the complete fresh signup flow:
@@ -27,7 +31,7 @@ func TestFreshSignup(t *testing.T) {
2731
// Ensure the user signup is not present in the system
2832
env := viper.GetString("ENVIRONMENT")
2933
username := viper.GetString("SSO_USERNAME")
30-
ensureNoUserSignup(t, env, username)
34+
ensureNoUserSignup(t, page, env, username)
3135

3236
// Step 2: Verify homepage layout on first access
3337
verifyHomepage(t, page)
@@ -39,8 +43,9 @@ func TestFreshSignup(t *testing.T) {
3943
verifyDevSandboxAccess(t, page, env, testName)
4044
}
4145

42-
func ensureNoUserSignup(t *testing.T, env, username string) {
43-
if env == sandboxui.TestEnv {
46+
func ensureNoUserSignup(t *testing.T, page playwright.Page, env, username string) {
47+
switch env {
48+
case sandboxui.TestEnv:
4449
awaitilities := testsupport.WaitForDeployments(t)
4550
hostAwait := awaitilities.Host()
4651
userSignup, err := sandboxui.WaitForUserSignup(t, hostAwait, username)
@@ -51,6 +56,18 @@ func ensureNoUserSignup(t *testing.T, env, username string) {
5156
// delete user signup
5257
err := sandboxui.DeleteUserSignup(t, hostAwait, userSignup)
5358
require.NoError(t, err)
59+
reloadPage(t, page)
60+
}
61+
case sandboxui.ProdEnv:
62+
client, err := newClient(t, viper.GetString("KUBECONFIG"))
63+
require.NoError(t, err)
64+
65+
userSignup := sandboxui.GetUserSignupWithClient(t, client, username)
66+
67+
if userSignup != nil {
68+
// delete user signup
69+
sandboxui.DeleteUserSignupWithClient(t, client, userSignup)
70+
reloadPage(t, page)
5471
}
5572
}
5673
}
@@ -126,17 +143,15 @@ func performSignup(t *testing.T, page playwright.Page, env, username string) {
126143
err = tryItButton.Click()
127144
require.NoError(t, err)
128145

129-
if env == sandboxui.TestEnv {
130-
// add signup to cleanup
131-
awaitilities := testsupport.WaitForDeployments(t)
132-
hostAwait := awaitilities.Host()
133-
userSignup, err := sandboxui.WaitForUserSignup(t, hostAwait, username)
134-
require.NoError(t, err)
135-
cleanup.AddCleanTasks(t, hostAwait.Client, userSignup)
136-
}
146+
t.Cleanup(func() {
147+
ensureNoUserSignup(t, nil, env, username)
148+
})
137149

138150
// wait for loading icon to disappear
139-
err = loadingIcon.WaitFor(playwright.LocatorWaitForOptions{State: playwright.WaitForSelectorStateHidden})
151+
err = loadingIcon.WaitFor(playwright.LocatorWaitForOptions{
152+
State: playwright.WaitForSelectorStateHidden,
153+
Timeout: playwright.Float(60000), // 1 minute timeout
154+
})
140155
require.NoError(t, err)
141156

142157
// wait for network to be idle (ensures all updates are complete)
@@ -188,23 +203,60 @@ func verifyDevSandboxAccess(t *testing.T, page playwright.Page, env, testName st
188203
devSandboxPage, err := sandboxui.ClickAndWaitForPopup(t, page, tryItBtn, testName)
189204
require.NoError(t, err)
190205

191-
img := devSandboxPage.GetByRole("img", playwright.PageGetByRoleOptions{
192-
Name: imgName,
193-
})
194-
err = img.WaitFor(playwright.LocatorWaitForOptions{
195-
Timeout: playwright.Float(30000),
196-
})
197-
require.NoError(t, err)
206+
if env == sandboxui.ProdEnv {
207+
// Wait for auth redirect to complete
208+
if strings.Contains(devSandboxPage.URL(), "/oauth/authorize") {
209+
err := devSandboxPage.WaitForURL("**/k8s/cluster/projects/**", playwright.PageWaitForURLOptions{
210+
Timeout: playwright.Float(180000), // 3 minutes
211+
})
212+
require.NoError(t, err)
213+
}
198214

199-
h := devSandboxPage.GetByRole("heading", playwright.PageGetByRoleOptions{})
200-
hText, err := h.TextContent()
201-
require.NoError(t, err)
202-
require.Contains(t, hText, logMessage)
215+
// Find welcome text and wait for it to be visible
216+
welcomeText := devSandboxPage.GetByText("Welcome to the new OpenShift experience!")
217+
err = welcomeText.WaitFor(playwright.LocatorWaitForOptions{
218+
State: playwright.WaitForSelectorStateVisible,
219+
Timeout: playwright.Float(180000), // 3 minutes
220+
})
221+
require.NoError(t, err)
222+
} else {
223+
img := devSandboxPage.GetByRole("img", playwright.PageGetByRoleOptions{
224+
Name: imgName,
225+
})
226+
err = img.WaitFor(playwright.LocatorWaitForOptions{
227+
Timeout: playwright.Float(30000),
228+
})
229+
require.NoError(t, err)
203230

204-
list := devSandboxPage.GetByRole("list", playwright.PageGetByRoleOptions{})
205-
listText, err := list.TextContent()
206-
require.NoError(t, err)
207-
require.Contains(t, listText, "DevSandbox")
231+
h := devSandboxPage.GetByRole("heading", playwright.PageGetByRoleOptions{})
232+
hText, err := h.TextContent()
233+
require.NoError(t, err)
234+
require.Contains(t, hText, logMessage)
235+
236+
list := devSandboxPage.GetByRole("list", playwright.PageGetByRoleOptions{})
237+
listText, err := list.TextContent()
238+
require.NoError(t, err)
239+
require.Contains(t, listText, "DevSandbox")
240+
}
208241

209242
require.NoError(t, devSandboxPage.Close())
210243
}
244+
245+
func newClient(t *testing.T, kubeconfigPath string) (client.Client, error) {
246+
require.NotEmpty(t, kubeconfigPath)
247+
248+
cfg, err := clientcmd.BuildConfigFromFlags("", kubeconfigPath)
249+
require.NoError(t, err)
250+
251+
s := runtime.NewScheme()
252+
require.NoError(t, toolchainv1alpha1.AddToScheme(s))
253+
254+
return client.New(cfg, client.Options{Scheme: s})
255+
}
256+
257+
func reloadPage(t *testing.T, page playwright.Page) {
258+
if page != nil {
259+
_, err := page.Reload()
260+
require.NoError(t, err)
261+
}
262+
}

testsupport/devsandbox-dashboard/login.go

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func NewLoginPage(page playwright.Page, environment string) *LoginPage {
2626
}
2727

2828
switch environment {
29-
case DevEnv:
29+
case DevEnv, ProdEnv:
3030
lp.LoginUsernameLoc = page.GetByRole("textbox", playwright.PageGetByRoleOptions{
3131
Name: "Red Hat login",
3232
})
@@ -59,19 +59,17 @@ func NewLoginPage(page playwright.Page, environment string) *LoginPage {
5959
}
6060

6161
func (lp *LoginPage) Navigate(t *testing.T, url string) {
62-
_, err := lp.Page.Goto(url)
62+
_, err := lp.Page.Goto(url, playwright.PageGotoOptions{
63+
Timeout: playwright.Float(60000), // 1 minute timeout
64+
})
6365
require.NoError(t, err)
6466
}
6567

6668
func (lp *LoginPage) Login(t *testing.T, loginUsername, loginPw string) {
67-
// Mask username field
68-
_, err := lp.LoginUsernameLoc.Evaluate(`element => element.style.webkitTextSecurity = 'disc'`, nil)
69+
err := lp.LoginUsernameLoc.Fill(loginUsername)
6970
require.NoError(t, err)
7071

71-
err = lp.LoginUsernameLoc.Fill(loginUsername)
72-
require.NoError(t, err)
73-
74-
if lp.Env == DevEnv {
72+
if lp.Env == DevEnv || lp.Env == ProdEnv {
7573
err := lp.NextBtn.Click()
7674
require.NoError(t, err)
7775
}

testsupport/devsandbox-dashboard/setup.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package sandboxui
22

33
import (
44
"fmt"
5+
"os"
56
"path/filepath"
67
"runtime"
78
"sync"
@@ -15,6 +16,7 @@ import (
1516
const (
1617
TestEnv = "ui-e2e-tests"
1718
DevEnv = "dev"
19+
ProdEnv = "prod"
1820
)
1921

2022
var (
@@ -62,8 +64,11 @@ func Setup(t *testing.T, testName string) playwright.Page {
6264
context, err := browser.NewContext(opts)
6365
require.NoError(t, err)
6466

65-
// save trace
66-
trace(t, context, testName)
67+
// save trace only if not running in CI
68+
// we do not want to expose sensitive information in CI
69+
if os.Getenv("ARTIFACT_DIR") == "" { // not CI environment
70+
trace(t, context, testName)
71+
}
6772

6873
page, err := context.NewPage()
6974
require.NoError(t, err)
@@ -73,9 +78,9 @@ func Setup(t *testing.T, testName string) playwright.Page {
7378
login := NewLoginPage(page, env)
7479
login.Navigate(t, baseURL)
7580

76-
if env == DevEnv {
81+
if env == ProdEnv {
7782
// handle cookie consent
78-
// on dev environment, the cookie consent appears after the login page is loaded
83+
// on prod environment, the cookie consent appears after the login page is loaded
7984
handleCookiesConsent(t, page)
8085
}
8186

testsupport/devsandbox-dashboard/trace.go

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,8 @@ func handleRecordedVideo(t *testing.T, page playwright.Page, targetVideoPath str
6868

6969
// Handle failed test - rename video
7070
if t.Failed() {
71-
// For popup videos, rename with UUID to avoid conflicts when multiple popups exist in the same test
72-
if strings.Contains(targetVideoPath, "popup") {
73-
uuid := filepath.Base(videoPath)
74-
uuid = strings.TrimSuffix(uuid, ".webm")
75-
if len(uuid) > 8 {
76-
uuid = uuid[:8] // Truncate to first 8 chars
77-
}
78-
targetVideoPath = strings.Replace(targetVideoPath, "popup", fmt.Sprintf("popup-%s", uuid), 1)
79-
}
80-
81-
if err := os.Rename(videoPath, targetVideoPath); err != nil {
71+
finalPath := buildPopupVideoPath(targetVideoPath, videoPath)
72+
if err := os.Rename(videoPath, finalPath); err != nil {
8273
t.Logf("failed to rename video %s: %v", videoPath, err)
8374
}
8475
return
@@ -90,3 +81,15 @@ func handleRecordedVideo(t *testing.T, page playwright.Page, targetVideoPath str
9081
}
9182
})
9283
}
84+
85+
func buildPopupVideoPath(targetPath, videoPath string) string {
86+
if !strings.Contains(targetPath, "popup") {
87+
return targetPath
88+
}
89+
uuid := filepath.Base(videoPath)
90+
uuid = strings.TrimSuffix(uuid, ".webm")
91+
if len(uuid) > 8 {
92+
uuid = uuid[:8]
93+
}
94+
return strings.Replace(targetPath, "popup", fmt.Sprintf("popup-%s", uuid), 1)
95+
}

0 commit comments

Comments
 (0)