Skip to content

Commit

Permalink
ROX-113658: Add first basic e2e tests for PF Network Graph (#5264)
Browse files Browse the repository at this point in the history
  • Loading branch information
vjwilson committed Mar 17, 2023
1 parent d17c743 commit 34aa0e8
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 3 deletions.
4 changes: 4 additions & 0 deletions ui/apps/platform/cypress/constants/NetworkPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ export const selectors = {
namespaceSelect: '.namespace-select > button',
filterSelect: search.multiSelectInput,
}),
selector: scopeSelectors('[data-testid="network-graph-selector-bar"]', {
clusterSelect: '.cluster-select > button',
namespaceSelect: '.namespace-select > button',
}),
errorOverlay: {
heading: 'h2:contains("An error has prevented the Network Graph from loading")',
message: (messageText) =>
Expand Down
108 changes: 108 additions & 0 deletions ui/apps/platform/cypress/helpers/networkGraphPF.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import * as api from '../constants/apiEndpoints';
import { selectors as networkGraphSelectors } from '../constants/NetworkPage';
import { interactAndWaitForResponses } from './request';
import { visit } from './visit';
import selectSelectors from '../selectors/select';
import navSelectors from '../selectors/navigation';
import { visitMainDashboard } from './main';

const networkGraphClusterAlias = 'networkgraph/cluster/id';
const networkPoliciesClusterAlias = 'networkpolicies/cluster/id';

const routeMatcherMapForClusterInNetworkGraph = {
[networkGraphClusterAlias]: {
method: 'GET',
url: api.network.networkGraph,
},
[networkPoliciesClusterAlias]: {
method: 'GET',
url: api.network.networkPoliciesGraph,
},
};

export function selectCluster() {
// TODO: update this test to use the new low-permission Clusters-Namespace endpoint after that is merged
// https://github.com/stackrox/stackrox/pull/4951
cy.intercept('POST', api.graphql('getClusterNamespaces')).as('getClusterNamespaces');

interactAndWaitForResponses(
() => {
cy.get(networkGraphSelectors.selector.clusterSelect).click();
cy.get(`${selectSelectors.patternFlySelect.openMenu} span:first`).click();
},
{
getClusterNamespaces: {
method: 'POST',
url: api.graphql('getClusterNamespaces'),
},
}
);
}

// Additional calls in a test can select additional namespaces.

export function selectNamespace(namespace) {
interactAndWaitForResponses(() => {
cy.get(networkGraphSelectors.selector.namespaceSelect).click();
// Exact match to distinguish stackrox from stackrox-operator namespaces.
cy.get(
`${selectSelectors.patternFlySelect.openMenu} .pf-c-select__menu-item [data-testid="namespace-name"]`
)
.contains(new RegExp(`^${namespace}$`))
.click();
cy.get(networkGraphSelectors.selector.namespaceSelect).click();
}, routeMatcherMapForClusterInNetworkGraph);
}

// visit helpers

export const notifiersAlias = 'notifiers';
export const clustersAlias = 'clusters';
export const networkPoliciesGraphEpochAlias = 'networkpolicies/graph/epoch';
export const searchMetadataOptionsAlias = 'search/metadata/options';

const routeMatcherMapToVisitNetworkGraph = {
// TODO: update this test to use the new low-permission Clusters endpoint after that is merged
// https://github.com/stackrox/stackrox/pull/4951
[clustersAlias]: {
method: 'GET',
url: '/v1/clusters',
},
[networkPoliciesGraphEpochAlias]: {
method: 'GET',
url: `${api.network.epoch}?clusterId=*`, // either id or null if no cluster selected
},
};

export const basePath = '/main/network-graph';

// TODO: replace this custom implementation with the version from
// import { visitFromLeftNav } from './nav';
// after the old network graph goes away in the left nav
function visitFromLeftNav(itemText, routeMatcherMap, staticResponseMap) {
visitMainDashboard();

interactAndWaitForResponses(
() => {
cy.get(`${navSelectors.navLinks}:contains("${itemText}")`).first().click();
},
routeMatcherMap,
staticResponseMap
);
}

export function visitNetworkGraphFromLeftNav() {
visitFromLeftNav('Network Graph', routeMatcherMapToVisitNetworkGraph);

cy.location('pathname').should('eq', basePath);
}

export function visitNetworkGraph(staticResponseMap) {
visit(basePath, routeMatcherMapToVisitNetworkGraph, staticResponseMap);
}

export function checkNetworkGraphEmptyState() {
cy.get(
'.pf-c-empty-state__content:contains("Select a cluster and at least one namespace to render active deployment traffic on the graph")'
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import navigationSelectors from '../../selectors/navigation';

import withAuth from '../../helpers/basicAuth';
import {
visitNetworkGraph,
visitNetworkGraphFromLeftNav,
checkNetworkGraphEmptyState,
selectCluster,
selectNamespace,
} from '../../helpers/networkGraphPF';
import { getRegExpForTitleWithBranding } from '../../helpers/title';
import { hasFeatureFlag } from '../../helpers/features';

describe('Network page', () => {
before(function beforeHook() {
if (!hasFeatureFlag('ROX_NETWORK_GRAPH_PATTERNFLY')) {
this.skip();
}
});

withAuth();

it('should visit using the left nav', () => {
visitNetworkGraphFromLeftNav();

cy.get(`${navigationSelectors.navLinks}:contains('Network Graph')`)
.first()
.should('have.class', 'pf-m-current');

checkNetworkGraphEmptyState();
});

it('should visit from direct navigation', () => {
visitNetworkGraph();

cy.title().should('match', getRegExpForTitleWithBranding('Network Graph'));

checkNetworkGraphEmptyState();
});

it('should render a graph when cluster and namespace are selected', () => {
visitNetworkGraph();

checkNetworkGraphEmptyState();

selectCluster();
selectNamespace('stackrox');

// check that group of nodes for NS is present
cy.get(
'.pf-ri__topology-demo .pf-topology-content [data-id="stackrox-active-graph"] [data-layer-id="groups"] [data-id="stackrox"]'
);

// check that label for NS is present
cy.get(
'.pf-ri__topology-demo .pf-topology-content [data-id="stackrox-active-graph"] [data-layer-id="default"] [data-id="stackrox"] text'
).contains('stackro');
});
});
9 changes: 8 additions & 1 deletion ui/apps/platform/cypress/support/e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,14 @@ Cypress.on('scrolled', ($el) => {
// - PR to add in Cypress core: https://github.com/cypress-io/cypress/pull/20257 (closed)
// - PR to add in Cypress core: https://github.com/cypress-io/cypress/pull/20284 (closed)
// - Comment with the original fix recommendation: https://github.com/cypress-io/cypress/issues/8418#issuecomment-992564877
//
// Addendum (2022-11-28): ignore error about multiple versions of Mobx
// The patternfly topology extension uses a 5.x version of Mobx, and the redoc library needs a 6.x version
//
// TODO: remove this catch for multiple MobX versions after the in-product documentation is removed
Cypress.on(
'uncaught:exception',
(err) => !err.message.includes('ResizeObserver loop limit exceeded')
(err) =>
!err.message.includes('ResizeObserver loop limit exceeded') &&
!err.message.includes('There are multiple, different versions of MobX active')
);
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ function ClusterSelector({

return (
<Select
className="cluster-select"
isPlain
placeholderText={
<span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ function NamespaceSelector({
isDisabled={namespace.deploymentCount < 1}
>
<span>
<NamespaceIcon /> {namespace.metadata.name}{' '}
<NamespaceIcon />
<span className="pf-u-mx-xs" data-testid="namespace-name">
{namespace.metadata.name}
</span>
<Badge isRead>{namespace.deploymentCount}</Badge>
</span>
</SelectOption>
Expand Down Expand Up @@ -104,7 +107,10 @@ function NamespaceSelector({
isDisabled={namespace.deploymentCount < 1}
>
<span>
<NamespaceIcon /> {namespace.metadata.name}{' '}
<NamespaceIcon />
<span className="pf-u-mx-xs" data-testid="namespace-name">
{namespace.metadata.name}
</span>
<Badge isRead>{namespace.deploymentCount}</Badge>
</span>
</SelectOption>
Expand Down

0 comments on commit 34aa0e8

Please sign in to comment.