From e0d71f02b1875e8128d139ba021a22709e131656 Mon Sep 17 00:00:00 2001 From: Ezequiel Victorero Date: Mon, 1 Aug 2022 11:20:49 -0300 Subject: [PATCH] Public Dashboards: add e2e tests for public dashboards (#52970) --- .../dashboard-public-create.spec.ts | 139 ++++++++++++++++++ .../dashboard-public-templating.spec.ts | 29 ++++ .../src/selectors/pages.ts | 15 ++ .../dashboard/components/DashNav/DashNav.tsx | 5 +- .../ShareModal/SharePublicDashboard.tsx | 21 ++- scripts/grafana-server/custom.ini | 2 +- 6 files changed, 207 insertions(+), 4 deletions(-) create mode 100644 e2e/dashboards-suite/dashboard-public-create.spec.ts create mode 100644 e2e/dashboards-suite/dashboard-public-templating.spec.ts diff --git a/e2e/dashboards-suite/dashboard-public-create.spec.ts b/e2e/dashboards-suite/dashboard-public-create.spec.ts new file mode 100644 index 00000000000..8ba601934bc --- /dev/null +++ b/e2e/dashboards-suite/dashboard-public-create.spec.ts @@ -0,0 +1,139 @@ +import { e2e } from '@grafana/e2e'; + +e2e.scenario({ + describeName: 'Create a public dashboard', + itName: 'Create a public dashboard', + addScenarioDataSource: false, + addScenarioDashBoard: false, + skipScenario: false, + scenario: () => { + // Opening a dashboard without template variables + e2e().intercept('/api/ds/query').as('query'); + e2e.flows.openDashboard({ uid: 'ZqZnVvFZz' }); + e2e().wait('@query'); + + // Open sharing modal + e2e.pages.ShareDashboardModal.shareButton().click(); + + // Select public dashboards tab + e2e.pages.ShareDashboardModal.PublicDashboard.Tab().click(); + + // Saving button should be disabled + e2e.pages.ShareDashboardModal.PublicDashboard.SaveConfigButton().should('be.disabled'); + + // Acknowledge checkboxes + e2e.pages.ShareDashboardModal.PublicDashboard.WillBePublicCheckbox().should('be.enabled').click({ force: true }); + e2e.pages.ShareDashboardModal.PublicDashboard.LimitedDSCheckbox().should('be.enabled').click({ force: true }); + e2e.pages.ShareDashboardModal.PublicDashboard.CostIncreaseCheckbox().should('be.enabled').click({ force: true }); + + // Switch on enabling toggle + e2e.pages.ShareDashboardModal.PublicDashboard.EnableSwitch().click({ force: true }); + + // Save configuration + e2e.pages.ShareDashboardModal.PublicDashboard.SaveConfigButton().click(); + + // e2e.pages.ShareDashboardModal.PublicDashboard.CopyUrlButton().click(); + + // Checkboxes should be disabled after saving configuration + e2e.pages.ShareDashboardModal.PublicDashboard.WillBePublicCheckbox().should('be.disabled'); + e2e.pages.ShareDashboardModal.PublicDashboard.LimitedDSCheckbox().should('be.disabled'); + e2e.pages.ShareDashboardModal.PublicDashboard.CostIncreaseCheckbox().should('be.disabled'); + + // Save config button should still be enabled + e2e.pages.ShareDashboardModal.PublicDashboard.SaveConfigButton().should('be.enabled'); + }, +}); + +e2e.scenario({ + describeName: 'Open a public dashboard', + itName: 'Open a public dashboard', + addScenarioDataSource: false, + addScenarioDashBoard: false, + skipScenario: false, + scenario: () => { + // Opening a dashboard without template variables + e2e().intercept('/api/ds/query').as('query'); + e2e.flows.openDashboard({ uid: 'ZqZnVvFZz' }); + e2e().wait('@query'); + + // Tag indicating a dashboard is public + e2e.pages.Dashboard.DashNav.publicDashboardTag().should('exist'); + + // Open sharing modal + e2e.pages.ShareDashboardModal.shareButton().click(); + + // Select public dashboards tab + e2e.pages.ShareDashboardModal.PublicDashboard.Tab().click(); + + // Make a request to public dashboards api endpoint without authentication + e2e.pages.ShareDashboardModal.PublicDashboard.CopyUrlInput() + .invoke('val') + .then((url) => { + e2e() + .clearCookies() + .request(getPublicDashboardAPIUrl(String(url))) + .then((resp) => { + expect(resp.status).to.eq(200); + }); + }); + }, +}); + +e2e.scenario({ + describeName: 'Disable a public dashboard', + itName: 'Disable a public dashboard', + addScenarioDataSource: false, + addScenarioDashBoard: false, + skipScenario: false, + scenario: () => { + // Opening a dashboard without template variables + e2e().intercept('/api/ds/query').as('query'); + e2e.flows.openDashboard({ uid: 'ZqZnVvFZz' }); + e2e().wait('@query'); + + // Open sharing modal + e2e.pages.ShareDashboardModal.shareButton().click(); + + // Select public dashboards tab + e2e.pages.ShareDashboardModal.PublicDashboard.Tab().click(); + + // All checkboxes should be disabled + e2e.pages.ShareDashboardModal.PublicDashboard.WillBePublicCheckbox().should('be.disabled'); + e2e.pages.ShareDashboardModal.PublicDashboard.LimitedDSCheckbox().should('be.disabled'); + e2e.pages.ShareDashboardModal.PublicDashboard.CostIncreaseCheckbox().should('be.disabled'); + + // Saving button should be enabled + e2e.pages.ShareDashboardModal.PublicDashboard.SaveConfigButton().should('be.enabled'); + + // save url before disabling public dashboard + e2e.pages.ShareDashboardModal.PublicDashboard.CopyUrlInput() + .invoke('val') + .then((text) => e2e().wrap(text).as('url')); + + // Switch off enabling toggle + e2e.pages.ShareDashboardModal.PublicDashboard.EnableSwitch().click({ force: true }); + + // Save configuration + e2e.pages.ShareDashboardModal.PublicDashboard.SaveConfigButton().click(); + + // Url should be hidden + e2e.pages.ShareDashboardModal.PublicDashboard.CopyUrlInput().should('not.exist'); + + // Make a request to public dashboards api endpoint without authentication + e2e() + .get('@url') + .then((url) => { + e2e() + .clearCookies() + .request({ url: getPublicDashboardAPIUrl(String(url)), failOnStatusCode: false }) + .then((resp) => { + expect(resp.status).to.eq(404); + }); + }); + }, +}); + +const getPublicDashboardAPIUrl = (url: string): string => { + let accessToken = url.split('/').pop(); + return `/api/public/dashboards/${accessToken}`; +}; diff --git a/e2e/dashboards-suite/dashboard-public-templating.spec.ts b/e2e/dashboards-suite/dashboard-public-templating.spec.ts new file mode 100644 index 00000000000..808cff56902 --- /dev/null +++ b/e2e/dashboards-suite/dashboard-public-templating.spec.ts @@ -0,0 +1,29 @@ +import { e2e } from '@grafana/e2e'; + +e2e.scenario({ + describeName: 'Create a public dashboard with template variables is disabled', + itName: 'Create a public dashboard with template variables is disabled', + addScenarioDataSource: false, + addScenarioDashBoard: false, + skipScenario: false, + scenario: () => { + // Opening a dashboard with template variables + e2e.flows.openDashboard({ uid: 'HYaGDGIMk' }); + + // Open sharing modal + e2e.pages.ShareDashboardModal.shareButton().click(); + + // Select public dashboards tab + e2e.pages.ShareDashboardModal.PublicDashboard.Tab().click(); + + // Warning Alert dashboard cannot be made public because it has template variables + e2e.pages.ShareDashboardModal.PublicDashboard.TemplateVariablesWarningAlert().should('be.visible'); + + // Configuration elements for public dashboards should not exist + e2e.pages.ShareDashboardModal.PublicDashboard.WillBePublicCheckbox().should('not.exist'); + e2e.pages.ShareDashboardModal.PublicDashboard.LimitedDSCheckbox().should('not.exist'); + e2e.pages.ShareDashboardModal.PublicDashboard.CostIncreaseCheckbox().should('not.exist'); + e2e.pages.ShareDashboardModal.PublicDashboard.EnableSwitch().should('not.exist'); + e2e.pages.ShareDashboardModal.PublicDashboard.SaveConfigButton().should('not.exist'); + }, +}); diff --git a/packages/grafana-e2e-selectors/src/selectors/pages.ts b/packages/grafana-e2e-selectors/src/selectors/pages.ts index 6dff1d14cac..a81bc793b36 100644 --- a/packages/grafana-e2e-selectors/src/selectors/pages.ts +++ b/packages/grafana-e2e-selectors/src/selectors/pages.ts @@ -50,6 +50,7 @@ export const Pages = { */ nav: 'Dashboard navigation', navV2: 'data-testid Dashboard navigation', + publicDashboardTag: 'data-testid public dashboard tag', }, SubMenu: { submenu: 'Dashboard submenu', @@ -177,6 +178,20 @@ export const Pages = { SharePanelModal: { linkToRenderedImage: 'Link to rendered image', }, + ShareDashboardModal: { + shareButton: 'Share dashboard or panel', + PublicDashboard: { + Tab: 'Tab Public Dashboard', + WillBePublicCheckbox: 'data-testid public dashboard will be public checkbox', + LimitedDSCheckbox: 'data-testid public dashboard limited datasources checkbox', + CostIncreaseCheckbox: 'data-testid public dashboard cost may increase checkbox', + EnableSwitch: 'data-testid public dashboard on off switch', + SaveConfigButton: 'data-testid public dashboard save config button', + CopyUrlInput: 'data-testid public dashboard copy url input', + CopyUrlButton: 'data-testid public dashboard copy url button', + TemplateVariablesWarningAlert: 'data-testid public dashboard disabled template variables alert', + }, + }, Explore: { url: '/explore', General: { diff --git a/public/app/features/dashboard/components/DashNav/DashNav.tsx b/public/app/features/dashboard/components/DashNav/DashNav.tsx index 57e6aedea52..48719217219 100644 --- a/public/app/features/dashboard/components/DashNav/DashNav.tsx +++ b/public/app/features/dashboard/components/DashNav/DashNav.tsx @@ -4,6 +4,7 @@ import { connect, ConnectedProps } from 'react-redux'; import { useLocation } from 'react-router-dom'; import { locationUtil, textUtil } from '@grafana/data'; +import { selectors as e2eSelectors } from '@grafana/e2e-selectors/src'; import { locationService } from '@grafana/runtime'; import { ButtonGroup, ModalsController, ToolbarButton, PageToolbar, useForceUpdate, Tag } from '@grafana/ui'; import { AppChromeUpdate } from 'app/core/components/AppChrome/AppChromeUpdate'; @@ -31,6 +32,8 @@ const mapDispatchToProps = { const connector = connect(null, mapDispatchToProps); +const selectors = e2eSelectors.pages.Dashboard.DashNav; + export interface OwnProps { dashboard: DashboardModel; isFullscreen: boolean; @@ -157,7 +160,7 @@ export const DashNav = React.memo((props) => { } if (dashboard.meta.publicDashboardEnabled) { - buttons.push(); + buttons.push(); } if (dashboard.uid && config.featureToggles.dashboardComments) { diff --git a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard.tsx b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard.tsx index c4b70a86377..5ab528d2c7c 100644 --- a/public/app/features/dashboard/components/ShareModal/SharePublicDashboard.tsx +++ b/public/app/features/dashboard/components/ShareModal/SharePublicDashboard.tsx @@ -1,5 +1,6 @@ import React, { useCallback, useEffect, useState } from 'react'; +import { selectors as e2eSelectors } from '@grafana/e2e-selectors/src'; import { reportInteraction } from '@grafana/runtime/src'; import { Alert, @@ -37,6 +38,8 @@ interface Acknowledgements { export const SharePublicDashboard = (props: Props) => { const dashboardVariables = props.dashboard.getVariables(); + const selectors = e2eSelectors.pages.ShareDashboardModal.PublicDashboard; + const [publicDashboard, setPublicDashboardConfig] = useState({ isEnabled: false, uid: '', @@ -93,7 +96,11 @@ export const SharePublicDashboard = (props: Props) => { <>

Welcome to Grafana public dashboards alpha!

{dashboardHasTemplateVariables(dashboardVariables) ? ( - + This dashboard cannot be made public because it has template variables ) : ( @@ -121,6 +128,7 @@ export const SharePublicDashboard = (props: Props) => { label="Your entire dashboard will be public" value={acknowledgements.public} disabled={publicDashboardPersisted(publicDashboard)} + data-testid={selectors.WillBePublicCheckbox} onChange={(e) => onAcknowledge('public', e.currentTarget.checked)} /> @@ -130,6 +138,7 @@ export const SharePublicDashboard = (props: Props) => { label="Publishing currently only works with a subset of datasources" value={acknowledgements.datasources} disabled={publicDashboardPersisted(publicDashboard)} + data-testid={selectors.LimitedDSCheckbox} onChange={(e) => onAcknowledge('datasources', e.currentTarget.checked)} /> { label="Making your dashboard public will cause queries to run each time the dashboard is viewed which may increase costs" value={acknowledgements.usage} disabled={publicDashboardPersisted(publicDashboard)} + data-testid={selectors.CostIncreaseCheckbox} onChange={(e) => onAcknowledge('usage', e.currentTarget.checked)} /> { { reportInteraction('grafana_dashboards_public_enable_clicked', { @@ -206,8 +217,10 @@ export const SharePublicDashboard = (props: Props) => { { @@ -228,7 +241,11 @@ export const SharePublicDashboard = (props: Props) => { severity="warning" /> )} - diff --git a/scripts/grafana-server/custom.ini b/scripts/grafana-server/custom.ini index cd4f4c9103d..1d2c1bd3fa0 100644 --- a/scripts/grafana-server/custom.ini +++ b/scripts/grafana-server/custom.ini @@ -1,2 +1,2 @@ [feature_toggles] -enable = +enable = publicDashboards