Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions ui/apps/platform/cypress/constants/VulnManagementPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ export const url = {
policy: `${baseURL}/policy`,
deployment: `${baseURL}/deployment`,
},
sidepanel: {
image: `${baseURL}/images?workflowState[0][t]=IMAGE&workflowState[0][i]=sha256:02382353821b12c21b062c59184e227e001079bb13ebd01f9d3270ba0fcbf1e4`,
node: `${baseURL}/nodes?workflowState[0][t]=NODE&workflowState[0][i]=065fe8cb-d9af-4516-a91e-3941e9db58ca`,
},
reporting: {
list: `${baseURL}/reports`,
create: `${baseURL}/reports?action=create`,
Expand Down Expand Up @@ -132,7 +128,6 @@ export const sidePanelListEntityPageSelectors = {
};

export const dashboardSelectors = {
applicationAndInfrastructureDropdown: 'button:contains("Application & Infrastructure")',
topRiskyItems: {
select: {
input: '[data-testid="widget"] .react-select__control',
Expand Down
71 changes: 0 additions & 71 deletions ui/apps/platform/cypress/constants/apiEndpoints.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,77 +205,6 @@ export const configMgmt = {
// Use graphqlPluralEntity or graphqlSingularEntity.
};

/*
* The following keys correspond to url list object in VulnManagementPage.js file.
*/

export const opnameForEntity = {
clusters: 'getCluster',
components: 'getComponent',
'image-components': 'getImageComponent',
'node-components': 'getComponent',
cves: 'getCve',
'image-cves': 'getCve',
'node-cves': 'getCve',
'cluster-cves': 'getCve',
deployments: 'getDeployment',
images: 'getImage',
namespaces: 'getNamespace',
nodes: 'getNode',
policies: 'getPolicy',
};

export const opnameForEntities = {
clusters: 'getClusters',
components: 'getComponents',
'image-components': 'getImageComponents',
'node-components': 'getNodeComponents',
cves: 'getCves',
'image-cves': 'getImageCves',
'node-cves': 'getNodeCves',
'cluster-cves': 'getClusterCves',
deployments: 'getDeployments',
images: 'getImages',
namespaces: 'getNamespaces',
nodes: 'getNodes',
policies: 'getPolicies',
};

export const opnamePrefixForPrimaryAndSecondaryEntities = {
clusters: 'getCluster_',
components: 'getComponentSubEntity',
'image-components': 'getComponentSubEntity',
'node-components': 'getNodeComponentSubEntity',
cves: 'getCve',
'image-cves': 'getCve',
'node-cves': 'getCve',
'cluster-cves': 'getCve',
deployments: 'getDeployment',
images: 'getImage',
namespaces: 'getNamespace',
nodes: 'getNode',
policies: 'getPolicy',
};

export const vulnMgmt = {
// For example, graphqlEntity('clusters')
graphqlEntity: (key) => graphql(opnameForEntity[key]),
// For example, graphqlEntities('clusters')
graphqlEntities: (key) => graphql(opnameForEntities[key]),
// For example, graphqlEntities2('clusters', 'CVE')
// prettier-ignore
graphqlEntities2: (key1, key2) => graphql(`${opnamePrefixForPrimaryAndSecondaryEntities[key1]}${key2}`),
graphqlOps: {
getCves: 'getCves',
getPolicies: 'getPolicies',
getPolicy: 'getPolicy',
getImage: 'getImage',
getNode: 'getNode',
getDeploymentCOMPONENT: 'getDeploymentCOMPONENT',
getFixableCvesForEntity: 'getFixableCvesForEntity',
},
};

export const integrationHealth = {
imageIntegrations: '/v1/integrationhealth/imageintegrations',
signatureIntegrations: '/v1/signatureintegrations',
Expand Down
2 changes: 1 addition & 1 deletion ui/apps/platform/cypress/helpers/compliance.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export function scanCompliance() {
cy.wait('@triggerScan');
waitForResponses(requestConfig);

cy.get(selectors.scanButton).click().should('not.have.attr', 'disabled');
cy.get(selectors.scanButton).should('not.have.attr', 'disabled');
}

/*
Expand Down
142 changes: 134 additions & 8 deletions ui/apps/platform/cypress/helpers/vulnmanagement/entities.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,59 @@ export function visitVulnerabilityManagementDashboard() {
cy.get('h1:contains("Vulnerability Management")');
}

const { opnameForEntity } = api; // TODO move here from apiEndpoints.js
/*
* The following keys correspond to url list object in VulnManagementPage.js file.
*/

const { opnameForEntities } = api; // TODO move here from apiEndpoints.js
const opnameForEntity = {
clusters: 'getCluster',
components: 'getComponent',
'image-components': 'getImageComponent',
'node-components': 'getComponent',
cves: 'getCve',
'image-cves': 'getCve',
'node-cves': 'getCve',
'cluster-cves': 'getCve',
deployments: 'getDeployment',
images: 'getImage',
namespaces: 'getNamespace',
nodes: 'getNode',
policies: 'getPolicy',
};

const { opnamePrefixForPrimaryAndSecondaryEntities } = api; // TODO move here from apiEndpoints.js
const opnameForEntities = {
clusters: 'getClusters',
components: 'getComponents',
'image-components': 'getImageComponents',
'node-components': 'getNodeComponents',
cves: 'getCves',
'image-cves': 'getImageCves',
'node-cves': 'getNodeCves',
'cluster-cves': 'getClusterCves',
deployments: 'getDeployments',
images: 'getImages',
namespaces: 'getNamespaces',
nodes: 'getNodes',
policies: 'getPolicies',
};

const keyForEntity = {
const opnamePrefixForPrimaryAndSecondaryEntities = {
clusters: 'getCluster_',
components: 'getComponentSubEntity',
'image-components': 'getComponentSubEntity',
'node-components': 'getNodeComponentSubEntity',
cves: 'getCve',
'image-cves': 'getCve',
'node-cves': 'getCve',
'cluster-cves': 'getCve',
deployments: 'getDeployment',
images: 'getImage',
namespaces: 'getNamespace',
nodes: 'getNode',
policies: 'getPolicy',
};

const typeOfEntity = {
clusters: 'CLUSTER',
components: 'COMPONENT',
'image-components': 'IMAGE_COMPONENT',
Expand All @@ -101,24 +147,104 @@ const keyForEntity = {
* For example, given 'deployments' and 'image' return: 'getDeploymentIMAGE'
*/
function opnameForPrimaryAndSecondaryEntities(entitiesKey1, entitiesKey2) {
return `${opnamePrefixForPrimaryAndSecondaryEntities[entitiesKey1]}${keyForEntity[entitiesKey2]}`;
return `${opnamePrefixForPrimaryAndSecondaryEntities[entitiesKey1]}${typeOfEntity[entitiesKey2]}`;
}

/*
* For example, visitVulnerabilityManagementEntities('cves')
* For example, visitVulnerabilityManagementEntities('policies', '?s[Policy]=Fixable Severity at least Important')
*/
export function visitVulnerabilityManagementEntities(entitiesKey, search = '') {
visit(`${url.list[entitiesKey]}${search}`, {
const requestConfig = {
routeMatcherMap: routeMatcherMapForOpnames([
'searchOptions',
opnameForEntities[entitiesKey],
]),
});
};

visit(`${url.list[entitiesKey]}${search}`, requestConfig);

cy.get(`h1:contains("${headingPlural[entitiesKey]}")`);
}

export function interactAndWaitForVulnerabilityManagementEntities(
interactionCallback,
entitiesKey,
staticResponseForEntities
) {
/*
* Unlike visit function above, omit searchOptions request
* to support tests to sort the table by a column.
* By the way, the tests do not call this function for the click
* to restore initial sorting, because the response has been cached.
*/
const opname = opnameForEntities[entitiesKey];
const requestConfig = {
routeMatcherMap: {
[opname]: api.graphql(opname),
},
};
const staticResponseMap = staticResponseForEntities && { [opname]: staticResponseForEntities };

interactAndWaitForResponses(interactionCallback, requestConfig, staticResponseMap);

cy.location('pathname').should('eq', url.list[entitiesKey]);
cy.get(`h1:contains("${headingPlural[entitiesKey]}")`);
}

export function visitVulnerabilityManagementEntityInSidePanel(
entitiesKey,
entityId,
staticResponseForEntity
) {
const pathname = url.list[entitiesKey];
const search = `?workflowState[0][t]=${typeOfEntity[entitiesKey]}&workflowState[0][i]=${entityId}`;
const opname = opnameForEntity[entitiesKey];
const requestConfig = {
routeMatcherMap: {
[opname]: api.graphql(opname),
},
};
const staticResponseMap = staticResponseForEntity && { [opname]: staticResponseForEntity };

visit(`${pathname}${search}`, requestConfig, staticResponseMap);
}

export function interactAndWaitForVulnerabilityManagementEntity(
interactionCallback,
entitiesKey,
staticResponseForEntity
) {
const opname = opnameForEntity[entitiesKey];
const requestConfig = {
routeMatcherMap: {
[opname]: api.graphql(opname),
},
};
const staticResponseMap = staticResponseForEntity && { [opname]: staticResponseForEntity };

interactAndWaitForResponses(interactionCallback, requestConfig, staticResponseMap);
}

export function interactAndWaitForVulnerabilityManagementSecondaryEntities(
interactionCallback,
entitiesKey1,
entitiesKey2,
staticResponseForSecondaryEntities
) {
const opname = opnameForPrimaryAndSecondaryEntities(entitiesKey1, entitiesKey2);
const requestConfig = {
routeMatcherMap: {
[opname]: api.graphql(opname),
},
};
const staticResponseMap = staticResponseForSecondaryEntities && {
[opname]: staticResponseForSecondaryEntities,
};

interactAndWaitForResponses(interactionCallback, requestConfig, staticResponseMap);
}

/*
* resultsFromRegExp: /^(\d+) (\D+)$/.exec(linkText)
* which assumes that linkText matches a more specific RegExp
Expand Down Expand Up @@ -213,7 +339,7 @@ export function verifySecondaryEntities(

// Tilde because link might be under either Contains or Matches.
// Match data-testid attribute of link to distinguish 1 IMAGE from 114 IMAGE COMPONENTS.
const relatedEntitiesSelector = `h2:contains("Related entities") ~ div ul li a[data-testid="${keyForEntity[entitiesKey2]}-tile-link"]:has('[data-testid="tileLinkSuperText"]:contains("${relatedEntitiesCount}")'):has('[data-testid="tile-link-value"]:contains("${relatedEntitiesNoun}")')`;
const relatedEntitiesSelector = `h2:contains("Related entities") ~ div ul li a[data-testid="${typeOfEntity[entitiesKey2]}-tile-link"]:has('[data-testid="tileLinkSuperText"]:contains("${relatedEntitiesCount}")'):has('[data-testid="tile-link-value"]:contains("${relatedEntitiesNoun}")')`;
cy.get(relatedEntitiesSelector);

// 4. Visit single page for primary entity.
Expand Down
Loading