Skip to content
Open
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
132 changes: 131 additions & 1 deletion frontend/src/routes/Governance/overview/Overview.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import {
mockPolicy,
mockPolicyNoStatus,
} from '../governance.sharedMocks'
import GovernanceOverview from './Overview'
import GovernanceOverview, { SecurityGroupViolations } from './Overview'
import { SecurityGroupPolicySummarySidebar } from './SecurityGroupPolicySummarySidebar'
import userEvent from '@testing-library/user-event'
import { defaultContext, PluginDataContext } from '../../../lib/PluginDataContext'
import { Policy, PolicyApiVersion, PolicyKind } from '../../../resources'

describe('Overview Page', () => {
beforeEach(async () => nockIgnoreApiPaths())
Expand Down Expand Up @@ -152,4 +154,132 @@ describe('Overview Page', () => {
userEvent.click(screen.getByText(/show 85 more/i))
expect(queryByText(/show 85 more/i)).not.toBeInTheDocument()
})

test('Should aggregate Standards card by trimmed annotation value, not raw comma-split token', async () => {
// Regression test: a standard listed anywhere but first in a comma-separated
// policy.open-cluster-management.io/standards annotation must not produce a
// separate row on the Standards card just because of the leading space left
// behind by String.split(',').
const policyWithStandardFirstInList: Policy = {
apiVersion: PolicyApiVersion,
kind: PolicyKind,
metadata: {
name: 'policy-standards-first',
namespace: 'test',
uid: 'standards-test-uid-1',
annotations: {
'policy.open-cluster-management.io/standards': 'NIST SP 800-53, PCI-DSS 4.0',
},
},
spec: {
disabled: false,
'policy-templates': [],
remediationAction: 'inform',
},
status: {
compliant: 'Compliant',
},
}
const policyWithStandardLastInList: Policy = {
apiVersion: PolicyApiVersion,
kind: PolicyKind,
metadata: {
name: 'policy-standards-last',
namespace: 'test',
uid: 'standards-test-uid-2',
annotations: {
'policy.open-cluster-management.io/standards': 'CIS OpenShift Benchmark, PCI-DSS 4.0, NIST SP 800-53',
},
},
spec: {
disabled: false,
'policy-templates': [],
remediationAction: 'inform',
},
status: {
compliant: 'Compliant',
},
}

const pluginData = {
...defaultContext,
loadStarted: true,
loadCompleted: true,
}
render(
<PluginDataContext.Provider value={pluginData}>
<RecoilRoot
initializeState={(snapshot) => {
snapshot.set(policiesState, [policyWithStandardFirstInList, policyWithStandardLastInList])
snapshot.set(managedClustersState, mockManagedClusters)
}}
>
<MemoryRouter>
<GovernanceOverview />
</MemoryRouter>
</RecoilRoot>
</PluginDataContext.Provider>
)

// Before the fix this rendered two separate rows/spans for the same logical
// standard (one from the untrimmed " NIST SP 800-53" split token).
expect(screen.getAllByText('NIST SP 800-53').length).toBe(1)
expect(screen.getAllByText('PCI-DSS 4.0').length).toBe(1)
})

test('SecurityGroupPolicySummarySidebar should match policies by trimmed annotation value', async () => {
// Regression test for the sidebar drill-down: a policy whose standard is not
// the first item in its comma-separated annotation must still match the
// clicked-on violation, which is keyed by the trimmed value.
const policyWithStandardLastInList: Policy = {
apiVersion: PolicyApiVersion,
kind: PolicyKind,
metadata: {
name: 'policy-standards-last-sidebar',
namespace: 'test',
uid: 'standards-test-uid-3',
annotations: {
'policy.open-cluster-management.io/standards': 'CIS OpenShift Benchmark, PCI-DSS 4.0, NIST SP 800-53',
},
},
spec: {
disabled: false,
'policy-templates': [],
remediationAction: 'inform',
},
status: {
compliant: 'Compliant',
},
}
const violation: SecurityGroupViolations = {
name: 'NIST SP 800-53',
compliant: 1,
noncompliant: 0,
pending: 0,
}

const pluginData = {
...defaultContext,
loadStarted: true,
loadCompleted: true,
}
render(
<PluginDataContext.Provider value={pluginData}>
<RecoilRoot
initializeState={(snapshot) => {
snapshot.set(policiesState, [policyWithStandardLastInList])
}}
>
<MemoryRouter>
<SecurityGroupPolicySummarySidebar violation={violation} secGroupName="standards" compliance="compliant" />
</MemoryRouter>
</RecoilRoot>
</PluginDataContext.Provider>
)

// Before the fix, the sidebar's filter compared the untrimmed " NIST SP 800-53"
// split token against violation.name ("NIST SP 800-53") and never matched,
// so the policy would not appear in this list.
expect(await screen.findByText('policy-standards-last-sidebar')).toBeInTheDocument()
})
})
2 changes: 1 addition & 1 deletion frontend/src/routes/Governance/overview/Overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ function useSecurityGroupViolations(group: string, policies: Policy[]) {
if (policy.spec.disabled) continue
const annotation = policy.metadata.annotations?.[`policy.open-cluster-management.io/${group}`]
if (!annotation) continue
const names = annotation.split(',')
const names = annotation.split(',').map((name) => name.trim())
for (const name of names) {
let v = clusterViolations[name]
if (!v) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export function SecurityGroupPolicySummarySidebar(props: {
if (!annotation) {
return false
}
const names = annotation.split(',')
const names = annotation.split(',').map((name) => name.trim())
for (const name of names) {
if (name === violation.name && policy.status?.compliant) {
return true
Expand Down