From 3f04c2aa65adfabe491ddaf3b0a08b72b8593ae0 Mon Sep 17 00:00:00 2001 From: Pawel Kosiec Date: Thu, 20 Jun 2024 09:56:13 +0200 Subject: [PATCH] Fix and enable instance details page UI tests (#1461) --- .../botkube_page_helpers_test.go | 21 ++++-- .../cloud_slack_dev_e2e_test.go | 15 ++-- .../slack_page_helpers_test.go | 71 ++++++++++++------- 3 files changed, 67 insertions(+), 40 deletions(-) diff --git a/test/cloud-slack-dev-e2e/botkube_page_helpers_test.go b/test/cloud-slack-dev-e2e/botkube_page_helpers_test.go index f427553d9..cf367f704 100644 --- a/test/cloud-slack-dev-e2e/botkube_page_helpers_test.go +++ b/test/cloud-slack-dev-e2e/botkube_page_helpers_test.go @@ -174,6 +174,7 @@ func (p *BotkubeCloudPage) FinishWizard(t *testing.T) { t.Log("Navigating to plugin selection") p.page.Screenshot("before-first-next") + time.Sleep(3 * time.Second) p.page.MustElementR("button", "/^Next$/i"). MustWaitEnabled(). // We need to wait, otherwise, we click the same 'Next' button twice before the query is executed, and we are not really @@ -183,6 +184,7 @@ func (p *BotkubeCloudPage) FinishWizard(t *testing.T) { p.page.Screenshot("after-first-next") t.Log("Using pre-selected plugins. Navigating to wizard summary") + time.Sleep(3 * time.Second) p.page.MustElementR("button", "/^Next$/i"). MustWaitEnabled(). // We need to wait, otherwise, we click the same 'Next' button twice before the query is executed, and we are not really @@ -191,26 +193,31 @@ func (p *BotkubeCloudPage) FinishWizard(t *testing.T) { p.page.Screenshot("after-second-next") t.Log("Submitting changes") + time.Sleep(3 * time.Second) p.page.MustElementR("button", "/^Deploy changes$/i"). MustWaitEnabled(). MustClick() p.page.Screenshot("after-deploy-changes") - // wait till gql mutation passes, and navigates to install details, otherwise, we could navigate to instance details with state 'draft' + // wait till gql mutation passes, and navigates to instance details, otherwise, we could navigate to instance details with state 'draft' p.page.MustWaitNavigation() p.page.Screenshot("after-deploy-changes-navigation") } func (p *BotkubeCloudPage) UpdateKubectlNamespace(t *testing.T) { t.Log("Updating 'kubectl' namespace property") - + p.openKubectlUpdateForm() - + p.page.MustElementR("input#root_defaultNamespace", "default").MustSelectAllText().MustInput("kube-system") p.page.Screenshot("after-changing-namespace-property") p.page.MustElementR("button", "/^Update$/i").MustClick() p.page.Screenshot("after-clicking-plugin-update") + t.Log("Moving to top left corner of the page") + p.page.Mouse.MustMoveTo(0, 0) + p.page.Screenshot("after-moving-to-top-left") + t.Log("Submitting changes") p.page.MustWaitStable() p.page.MustElementR("button", "/Deploy changes/i").MustClick() @@ -230,10 +237,12 @@ func (p *BotkubeCloudPage) openKubectlUpdateForm() { p.page.MustWaitStable() p.page.Screenshot("after-selecting-plugins-tab") - - p.page.MustElement(`button[id^="botkube/kubectl_"]`).MustClick() + + p.page.MustElement(`button[id^="botkube/kubectl_"]`). + MustWaitEnabled(). // needed as we have an "Outdated version detected" glitch + MustClick() p.page.Screenshot("after-opening-kubectl-cfg") - + p.page.MustElement(`div[data-node-key="ui-form"]`).MustClick() p.page.Screenshot("after-selecting-kubectl-cfg-form") } diff --git a/test/cloud-slack-dev-e2e/cloud_slack_dev_e2e_test.go b/test/cloud-slack-dev-e2e/cloud_slack_dev_e2e_test.go index d86c71843..3ae3b18d2 100644 --- a/test/cloud-slack-dev-e2e/cloud_slack_dev_e2e_test.go +++ b/test/cloud-slack-dev-e2e/cloud_slack_dev_e2e_test.go @@ -42,7 +42,7 @@ type E2ESlackConfig struct { Slack SlackConfig BotkubeCloud BotkubeCloudConfig - PageTimeout time.Duration `envconfig:"default=5m"` + PageTimeout time.Duration `envconfig:"default=10m"` ScreenshotsDir string `envconfig:"optional"` DebugMode bool `envconfig:"default=false"` @@ -152,20 +152,17 @@ func TestCloudSlackE2E(t *testing.T) { botkubeCloudPage.InstallAgentInCluster(t, cfg.BotkubeCliBinaryPath) botkubeCloudPage.OpenSlackAppIntegrationPage(t) - slackPage.ConnectWorkspace(t, isHeadless, browser) + slackPage.ConnectWorkspace(t, browser) botkubeCloudPage.ReAddSlackPlatformIfShould(t, isHeadless) botkubeCloudPage.SetupSlackWorkspace(t, channel.Name()) botkubeCloudPage.FinishWizard(t) botkubeCloudPage.VerifyDeploymentStatus(t, "Connected") - if !isHeadless { // it is flaky on CI, more investigation needed - botkubeCloudPage.UpdateKubectlNamespace(t) - botkubeCloudPage.VerifyDeploymentStatus(t, "Updating") - botkubeCloudPage.VerifyDeploymentStatus(t, "Connected") - botkubeCloudPage.VerifyUpdatedKubectlNamespace(t) - } - + botkubeCloudPage.UpdateKubectlNamespace(t) + botkubeCloudPage.VerifyDeploymentStatus(t, "Updating") + botkubeCloudPage.VerifyDeploymentStatus(t, "Connected") + botkubeCloudPage.VerifyUpdatedKubectlNamespace(t) }) t.Run("Run E2E tests with deployment", func(t *testing.T) { diff --git a/test/cloud-slack-dev-e2e/slack_page_helpers_test.go b/test/cloud-slack-dev-e2e/slack_page_helpers_test.go index e516c2c93..f6397885d 100644 --- a/test/cloud-slack-dev-e2e/slack_page_helpers_test.go +++ b/test/cloud-slack-dev-e2e/slack_page_helpers_test.go @@ -3,71 +3,92 @@ package cloud_slack_dev_e2e import ( + "context" + "errors" + "github.com/stretchr/testify/assert" "testing" "time" "github.com/go-rod/rod" ) -const slackBaseURL = "slack.com" +const ( + slackBaseURL = "slack.com" + waitTime = 10 * time.Second + contextTimeout = 30 * time.Second + shorterContextTimeout = 10 * time.Second +) type SlackPage struct { page *Page - cfg SlackConfig + cfg E2ESlackConfig } func NewSlackPage(t *testing.T, cfg E2ESlackConfig) *SlackPage { return &SlackPage{ page: &Page{t: t, cfg: cfg}, - cfg: cfg.Slack, + cfg: cfg, } } -func (p *SlackPage) ConnectWorkspace(t *testing.T, headless bool, browser *rod.Browser) { +func (p *SlackPage) ConnectWorkspace(t *testing.T, browser *rod.Browser) { p.page.Page = browser.MustPages().MustFindByURL(slackBaseURL) + p.page.MustWaitStable() - p.page.MustElement("input#domain").MustInput(p.cfg.WorkspaceName) - + defer func(page *Page) { + err := page.Close() + if err != nil { + if errors.Is(err, context.Canceled) { + return + } + t.Fatalf("Failed to close page: %s", err.Error()) + } + }(p.page) + + p.page.MustElement("input#domain").MustInput(p.cfg.Slack.WorkspaceName) p.page.MustElementR("button", "Continue").MustClick() - p.page.Screenshot() - - // here we get reloaded, so we need to type it again (looks like bug on Slack side) - if !headless { - p.page.MustElement("input#domain").MustInput(p.cfg.WorkspaceName) - p.page.MustElementR("button", "Continue").MustClick() - } + p.page.Screenshot("after-continue") p.page.MustWaitStable() p.page.MustElementR("a", "sign in with a password instead").MustClick() - p.page.Screenshot() - p.page.MustElement("input#email").MustInput(p.cfg.Email) - p.page.MustElement("input#password").MustInput(p.cfg.Password) + p.page.Screenshot("after-sign-in-with-password") + p.page.MustElement("input#email").MustInput(p.cfg.Slack.Email) + p.page.MustElement("input#password").MustInput(p.cfg.Slack.Password) p.page.Screenshot() t.Log("Hide Slack cookie banner that collides with 'Sign in' button") - cookie, err := p.page.Timeout(5 * time.Second).Element("button#onetrust-accept-btn-handler") + pageWithTimeout := p.page.Timeout(shorterContextTimeout) + t.Cleanup(func() { + _ = pageWithTimeout.Close() + }) + + cookieElem, err := pageWithTimeout.Element("button#onetrust-accept-btn-handler") if err != nil { t.Logf("Failed to obtain cookie element: %s. Skipping...", err.Error()) } else { - cookie.MustClick() + cookieElem.MustClick() } p.page.MustElementR("button", "/^Sign in$/i").MustClick() - p.page.Screenshot() + p.page.Screenshot("after-sign-in") + time.Sleep(waitTime) // ensure the screenshots shows a page after "Sign in" click + p.page.Screenshot("after-sign-in-page") p.page.MustElementR("button.c-button:not(.c-button--disabled)", "Allow").MustClick() t.Log("Finalizing Slack workspace connection...") - if p.cfg.WorkspaceAlreadyConnected { + if p.cfg.Slack.WorkspaceAlreadyConnected { t.Log("Expecting already connected message...") p.page.MustElementR("div.ant-result-title", "Organization Already Connected!") } else { t.Log("Finalizing connection...") - p.page.Screenshot() - p.page.MustElement("button#slack-workspace-connect").MustClick(). - MustWaitEnabled() // when it's re-enabled, then it means the query was finished - p.page.Screenshot() + time.Sleep(waitTime) + p.page.Screenshot("before-workspace-connect") + p.page.MustElement("button#slack-workspace-connect").MustClick() + p.page.Screenshot("after-workspace-connect") } - _ = p.page.Close() // the page should be closed automatically anyway + t.Log("Waiting for page auto-close...") + err = p.page.WaitIdle(waitTime) // wait for auto-close + assert.NoError(t, err) }