Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
73 changes: 73 additions & 0 deletions frontend/src/routes/Governance/overview/Overview.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
import GovernanceOverview from './Overview'
import userEvent from '@testing-library/user-event'
import { defaultContext, PluginDataContext } from '../../../lib/PluginDataContext'
import { Policy, PolicyApiVersion, PolicyKind } from '../../../resources'
Comment on lines +16 to +20

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use aliases and type-only imports.

SecurityGroupViolations and Policy are type-only; the newly added internal imports are relative. Split type imports with import type and use ~/... aliases for the new internal imports.

As per coding guidelines, use ~/ shorthand and import type for type-only imports.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/routes/Governance/overview/Overview.test.tsx` around lines 16 -
20, Update the imports in the Overview test to use the ~/ alias for newly added
internal module imports, and split SecurityGroupViolations and Policy into
import type declarations because they are type-only symbols. Preserve the
existing value imports and runtime behavior.

Source: Coding guidelines


describe('Overview Page', () => {
beforeEach(async () => nockIgnoreApiPaths())
Expand Down Expand Up @@ -141,4 +142,76 @@ 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)
}}
Comment on lines +200 to +204

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use shared atom access for the new fixtures.

Both tests set policiesState (and one sets managedClustersState) through direct atom imports.

  • frontend/src/routes/Governance/overview/Overview.test.tsx#L200-L204: initialize the policy and cluster fixtures through useSharedAtoms().
  • frontend/src/routes/Governance/overview/Overview.test.tsx#L257-L260: initialize the policy fixture through useSharedAtoms().

As per coding guidelines, mock Recoil atoms via useSharedAtoms() rather than direct atom imports.

📍 Affects 1 file
  • frontend/src/routes/Governance/overview/Overview.test.tsx#L200-L204 (this comment)
  • frontend/src/routes/Governance/overview/Overview.test.tsx#L257-L260
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/routes/Governance/overview/Overview.test.tsx` around lines 200 -
204, Replace direct atom initialization in both test fixtures with shared atom
access via useSharedAtoms(). In
frontend/src/routes/Governance/overview/Overview.test.tsx:200-204, initialize
both the policy and managed-cluster fixtures through useSharedAtoms(); at
257-260, initialize the policy fixture the same way, removing direct atom
imports or usage where applicable.

Source: Coding guidelines

>
<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)
})
})
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 @@ -100,7 +100,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