From 24a6af508f9e7a4b81b3683d71c402c18ce1d81e Mon Sep 17 00:00:00 2001 From: Mateusz Szostok Date: Tue, 18 Jun 2024 16:12:36 +0200 Subject: [PATCH] Add temporary workflow to test e2e tests --- .../botkube_page_helpers_test.go | 44 ++++++++++----- .../cloud_slack_dev_e2e_test.go | 55 ++++++++++--------- test/cloud-slack-dev-e2e/page_helpers_test.go | 15 +++-- 3 files changed, 71 insertions(+), 43 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 2ad58294d..0d92196a8 100644 --- a/test/cloud-slack-dev-e2e/botkube_page_helpers_test.go +++ b/test/cloud-slack-dev-e2e/botkube_page_helpers_test.go @@ -160,7 +160,7 @@ func (p *BotkubeCloudPage) SetupSlackWorkspace(t *testing.T, channel string) { // filter by channel, to make sure that it's visible on the first table page, in order to select it in the next step t.Log("Filtering by channel name") - p.page.Mouse.MustScroll(10, 5000) // scroll bottom, as the footer collides with selecting filter + p.page.Mouse.MustScroll(10, 5000) // scroll bottom, as the footer collides with selecting filter p.page.Screenshot() p.page.MustElement("table th:nth-child(3) span.ant-dropdown-trigger.ant-table-filter-trigger").MustClick() @@ -172,40 +172,58 @@ func (p *BotkubeCloudPage) SetupSlackWorkspace(t *testing.T, channel string) { func (p *BotkubeCloudPage) FinishWizard(t *testing.T) { t.Log("Navigating to plugin selection") - p.page.Screenshot() - - p.page.MustElementR("button", "/^Next$/i").MustClick() - p.page.Screenshot() + p.page.Screenshot("before-first-next") + + 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 really + // moved to the next step. If we have the navigation updated for each step, it will be resolved. + MustClick().MustWaitStable() + + p.page.Screenshot("after-first-next") t.Log("Using pre-selected plugins. Navigating to wizard summary") - p.page.MustElementR("button", "/^Next$/i").MustClick() - p.page.Screenshot() + 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 really + // moved to the next step. If we have the navigation updated for each step, it will be resolved. + MustClick().MustWaitStable() + p.page.Screenshot("after-second-next") t.Log("Submitting changes") - p.page.MustElementR("button", "/^Deploy changes$/i").MustClick() + 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' + p.page.MustWaitNavigation() p.page.Screenshot() } func (p *BotkubeCloudPage) UpdateKubectlNamespace(t *testing.T) { t.Log("Updating 'kubectl' namespace property") - p.page.MustElementR(`div[role="tab"]`, "Plugins").MustClick() + p.page.MustElementR(`div[role="tab"]`, "Plugins").MustFocus().MustClick().MustWaitStable() + + p.page.MustWaitStable() p.page.MustElement(`button[id^="botkube/kubectl_"]`).MustClick() p.page.MustElement(`div[data-node-key="ui-form"]`).MustClick() p.page.MustElementR("input#root_defaultNamespace", "default").MustSelectAllText().MustInput("kube-system") p.page.MustElementR("button", "/^Update$/i").MustClick() t.Log("Submitting changes") - p.page.MustElementR("button", "/^Deploy changes$/i").MustClick().MustWaitStable() // use the case-insensitive flag "i" + p.page.MustElementR("button", "/^Deploy changes$/i").MustClick().MustWaitStable() } func (p *BotkubeCloudPage) VerifyUpdatedKubectlNamespace(t *testing.T) { t.Log("Verifying that the 'namespace' value was updated and persisted properly") - p.page.Screenshot() - p.page.MustElementR(`div[role="tab"]`, "Plugins").MustClick() + p.page.Screenshot("before-selecting-plugins-tab") + p.page.MustElementR(`div[role="tab"]`, "Plugins").MustFocus().MustClick().MustWaitStable() + p.page.Screenshot("after-selecting-plugins-tab") p.page.MustElement(`button[id^="botkube/kubectl_"]`).MustClick() p.page.MustElement(`div[data-node-key="ui-form"]`).MustClick() - p.page.Screenshot() + p.page.Screenshot("after-selecting-kubectl-cfg-form") p.page.MustElementR("input#root_defaultNamespace", "kube-system") } 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 738433b9d..90c698764 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 @@ -21,6 +21,7 @@ import ( "github.com/go-rod/rod/lib/launcher" "github.com/go-rod/rod/lib/launcher/flags" "github.com/hasura/go-graphql-client" + "github.com/sanity-io/litter" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/vrischmann/envconfig" @@ -436,40 +437,40 @@ func removeSourcesAndAddActions(t *testing.T, gql *graphql.Client, existingDeplo var updateInput struct { UpdateDeployment gqlModel.Deployment `graphql:"updateDeployment(id: $id, input: $input)"` } + var updatePluginGroup []*gqlModel.PluginConfigurationGroupUpdateInput for _, createdPlugin := range existingDeployment.Plugins { - var pluginConfigs []*gqlModel.PluginConfigurationUpdateInput - pluginConfig := gqlModel.PluginConfigurationUpdateInput{ - Name: createdPlugin.ConfigurationName, - Configuration: createdPlugin.Configuration, - } - pluginConfigs = append(pluginConfigs, &pluginConfig) - plugin := gqlModel.PluginConfigurationGroupUpdateInput{ - ID: &createdPlugin.ID, - Name: createdPlugin.Name, - Type: createdPlugin.Type, - DisplayName: createdPlugin.DisplayName, - Configurations: pluginConfigs, - } - updatePluginGroup = append(updatePluginGroup, &plugin) - } - var updatePlugins []*gqlModel.PluginsUpdateInput - updatePlugin := gqlModel.PluginsUpdateInput{ - Groups: updatePluginGroup, + updatePluginGroup = append(updatePluginGroup, &gqlModel.PluginConfigurationGroupUpdateInput{ + ID: &createdPlugin.ID, + Name: createdPlugin.Name, + Type: createdPlugin.Type, + DisplayName: createdPlugin.DisplayName, + Configurations: []*gqlModel.PluginConfigurationUpdateInput{ + { + Name: createdPlugin.ConfigurationName, + Configuration: createdPlugin.Configuration, + }, + }, + }) } - updatePlugins = append(updatePlugins, &updatePlugin) platforms := gqlModel.PlatformsUpdateInput{} - for _, slack := range existingDeployment.Platforms.CloudSlacks { var channelUpdateInputs []*gqlModel.ChannelBindingsByNameAndIDUpdateInput for _, channel := range slack.Channels { + var executors []*string + for _, e := range channel.Bindings.Executors { + if strings.Contains(strings.ToLower(e), "ai") { // AI is also a source plugin + continue + } + executors = append(executors, &e) + } channelUpdateInputs = append(channelUpdateInputs, &gqlModel.ChannelBindingsByNameAndIDUpdateInput{ ChannelID: "", // this is used for UI only so we don't need to provide it Name: channel.Name, Bindings: &gqlModel.BotBindingsUpdateInput{ - Sources: nil, - Executors: []*string{&channel.Bindings.Executors[0]}, + Sources: []*string{}, + Executors: executors, }, }) } @@ -486,14 +487,18 @@ func removeSourcesAndAddActions(t *testing.T, gql *graphql.Client, existingDeplo "input": gqlModel.DeploymentUpdateInput{ Name: existingDeployment.Name, ResourceVersion: existingDeployment.ResourceVersion, - Plugins: updatePlugins, - Platforms: &platforms, - Actions: CreateActionUpdateInput(existingDeployment), + Plugins: []*gqlModel.PluginsUpdateInput{ + {Groups: updatePluginGroup}, + }, + Platforms: &platforms, + Actions: CreateActionUpdateInput(existingDeployment), }, } + litter.Dump(updateVariables) err := gql.Mutate(context.Background(), &updateInput, updateVariables) require.NoError(t, err) + litter.Dump(updateInput.UpdateDeployment) return &updateInput.UpdateDeployment } diff --git a/test/cloud-slack-dev-e2e/page_helpers_test.go b/test/cloud-slack-dev-e2e/page_helpers_test.go index 6b1c8f16f..00fb184b3 100644 --- a/test/cloud-slack-dev-e2e/page_helpers_test.go +++ b/test/cloud-slack-dev-e2e/page_helpers_test.go @@ -23,7 +23,7 @@ const ( // Currently, we get: // This browser won’t be supported starting September 1st, 2024. Update your browser to keep using Slack. Learn more: // https://slack.com/intl/en-gb/help/articles/1500001836081-Slack-support-life-cycle-for-operating-systems-app-versions-and-browsers - chromeUserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" + chromeUserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" ) type Page struct { @@ -32,7 +32,7 @@ type Page struct { cfg E2ESlackConfig } -func (p Page) Screenshot() { +func (p Page) Screenshot(suffix ...string) { p.t.Helper() if p.cfg.ScreenshotsDir == "" { return @@ -41,7 +41,7 @@ func (p Page) Screenshot() { pathParts := strings.Split(p.cfg.ScreenshotsDir, "/") pathParts = append(pathParts) - filePath := filepath.Join(p.cfg.ScreenshotsDir, fmt.Sprintf("%d.png", time.Now().UnixNano())) + filePath := filepath.Join(p.cfg.ScreenshotsDir, fmt.Sprintf("%d%s.png", time.Now().UnixNano(), screenshotSuffix(suffix))) logMsg := fmt.Sprintf("Saving screenshot to %q", filePath) if p.cfg.DebugMode { @@ -63,6 +63,13 @@ func (p Page) Screenshot() { assert.NoError(p.t, err) } +func screenshotSuffix(suffix []string) string { + if len(suffix) == 0 { + return "" + } + return "-" + strings.Join(suffix, "-") +} + func closePage(t *testing.T, name string, page *rod.Page) { t.Helper() err := page.Close() @@ -75,7 +82,6 @@ func closePage(t *testing.T, name string, page *rod.Page) { } } - func newBrowserPage(t *testing.T, browser *rod.Browser, cfg E2ESlackConfig) *rod.Page { t.Helper() @@ -88,4 +94,3 @@ func newBrowserPage(t *testing.T, browser *rod.Browser, cfg E2ESlackConfig) *rod page.MustSetViewport(1200, 1080, 1, false) return page } -