Skip to content

Commit 99389a1

Browse files
[scanner] fix: add tests for cluster utility components (#19243)
Signed-off-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent c627d78 commit 99389a1

4 files changed

Lines changed: 494 additions & 282 deletions

File tree

Lines changed: 134 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { describe, it, expect, vi, beforeEach } from 'vitest'
1+
import { describe, it, expect, vi } from 'vitest'
22
import { render, screen } from '@testing-library/react'
33
import { ClusterAuthBadges, ClusterIAMRefreshHint } from './ClusterAuthBadges'
44
import type { ClusterInfo } from '../../../hooks/useMCP'
@@ -8,145 +8,176 @@ vi.mock('react-i18next', () => ({
88
useTranslation: () => ({ t: (key: string) => key }),
99
}))
1010

11-
vi.mock('../../../lib/clipboard', () => ({
12-
copyToClipboard: vi.fn(),
13-
}))
14-
1511
describe('ClusterAuthBadges', () => {
16-
it('renders IAM badge and exec login hint in the title', () => {
17-
const cluster = { authMethod: 'exec', name: 'eks-prod', user: 'aws-user' } as ClusterInfo
18-
12+
it('renders IAM badge for exec auth method', () => {
13+
const cluster = { authMethod: 'exec', name: 'test', user: 'test' } as ClusterInfo
1914
render(<ClusterAuthBadges cluster={cluster} className="test-class" />)
2015

2116
const badge = screen.getByText('IAM')
17+
expect(badge).toBeInTheDocument()
2218
expect(badge).toHaveClass('test-class')
23-
expect(badge).toHaveAttribute('title', expect.stringContaining('aws sso login'))
2419
})
2520

26-
it('renders token and certificate badges for supported auth methods', () => {
27-
const { rerender } = render(
28-
<ClusterAuthBadges
29-
cluster={{ authMethod: 'token', name: 'demo', user: 'demo' } as ClusterInfo}
30-
className="token-class"
31-
/>,
32-
)
21+
it('renders token badge for token auth method', () => {
22+
const cluster = { authMethod: 'token', name: 'test', user: 'test' } as ClusterInfo
23+
render(<ClusterAuthBadges cluster={cluster} className="test-class" />)
3324

3425
expect(screen.getByText('token')).toBeInTheDocument()
26+
})
3527

36-
rerender(
37-
<ClusterAuthBadges
38-
cluster={{ authMethod: 'certificate', name: 'demo', user: 'demo' } as ClusterInfo}
39-
className="cert-class"
40-
/>,
41-
)
28+
it('renders cert badge for certificate auth method', () => {
29+
const cluster = { authMethod: 'certificate', name: 'test', user: 'test' } as ClusterInfo
30+
render(<ClusterAuthBadges cluster={cluster} className="test-class" />)
4231

4332
expect(screen.getByText('cert')).toBeInTheDocument()
4433
})
4534

46-
it('returns null for missing or unsupported auth methods', () => {
47-
const { container, rerender } = render(
48-
<ClusterAuthBadges cluster={{ name: 'demo' } as ClusterInfo} className="ignored" />,
49-
)
35+
it('renders IAM badge for auth-provider auth method', () => {
36+
const cluster = { authMethod: 'auth-provider', name: 'test', user: 'test' } as ClusterInfo
37+
render(<ClusterAuthBadges cluster={cluster} className="test-class" />)
38+
39+
expect(screen.getByText('IAM')).toBeInTheDocument()
40+
})
41+
42+
it('returns null when authMethod is not set', () => {
43+
const cluster = { name: 'test' } as ClusterInfo
44+
const { container } = render(<ClusterAuthBadges cluster={cluster} className="test-class" />)
5045

5146
expect(container.firstChild).toBeNull()
47+
})
5248

53-
rerender(
54-
<ClusterAuthBadges
55-
cluster={{ authMethod: 'custom', name: 'demo' } as ClusterInfo}
56-
className="ignored"
57-
/>,
58-
)
49+
it('returns null when authMethod is unknown', () => {
50+
const cluster = { authMethod: 'unknown-method', name: 'test' } as ClusterInfo
51+
const { container } = render(<ClusterAuthBadges cluster={cluster} className="test-class" />)
5952

6053
expect(container.firstChild).toBeNull()
6154
})
55+
56+
it('includes login hint in title for exec auth with AWS', () => {
57+
const cluster = { authMethod: 'exec', user: 'aws-user', name: 'test' } as ClusterInfo
58+
render(<ClusterAuthBadges cluster={cluster} className="test-class" />)
59+
60+
const badge = screen.getByText('IAM')
61+
expect(badge).toHaveAttribute('title', expect.stringContaining('aws sso login'))
62+
})
63+
64+
it('does not include login hint in title for exec auth without provider detection', () => {
65+
const cluster = { authMethod: 'exec', user: 'unknown', name: 'test' } as ClusterInfo
66+
render(<ClusterAuthBadges cluster={cluster} className="test-class" />)
67+
68+
const badge = screen.getByText('IAM')
69+
expect(badge).toHaveAttribute('title', 'Auth: IAM (exec plugin)')
70+
})
6271
})
6372

6473
describe('ClusterIAMRefreshHint', () => {
6574
beforeEach(() => {
66-
vi.clearAllMocks()
67-
})
68-
69-
it('renders an IAM login hint for expired exec tokens', () => {
70-
render(
71-
<ClusterIAMRefreshHint
72-
cluster={{
73-
authMethod: 'exec',
74-
user: 'aws-user',
75-
name: 'demo',
76-
errorType: 'auth',
77-
reachable: false,
78-
} as ClusterInfo}
79-
className="hint-class"
80-
/>,
81-
)
75+
Object.assign(navigator, {
76+
clipboard: {
77+
writeText: vi.fn().mockResolvedValue(undefined),
78+
},
79+
})
80+
})
81+
82+
it('renders login hint for exec auth with expired token', () => {
83+
const cluster = {
84+
authMethod: 'exec',
85+
user: 'aws-user',
86+
name: 'test',
87+
errorType: 'auth',
88+
reachable: false,
89+
} as ClusterInfo
90+
render(<ClusterIAMRefreshHint cluster={cluster} className="test-class" />)
8291

83-
expect(screen.getByText(/Login:/)).toBeInTheDocument()
8492
expect(screen.getByText('aws sso login')).toBeInTheDocument()
85-
expect(screen.getByLabelText('Copy command to clipboard')).toBeInTheDocument()
93+
expect(screen.getByText(/Login:/)).toBeInTheDocument()
8694
})
8795

88-
it('supports custom and omitted labels', () => {
89-
const { rerender } = render(
90-
<ClusterIAMRefreshHint
91-
cluster={{
92-
authMethod: 'exec',
93-
user: 'az-user',
94-
name: 'demo',
95-
errorType: 'auth',
96-
reachable: false,
97-
} as ClusterInfo}
98-
className="hint-class"
99-
label="Custom:"
100-
/>,
101-
)
96+
it('renders login hint for unreachable exec cluster', () => {
97+
const cluster = {
98+
authMethod: 'exec',
99+
user: 'gke-user',
100+
name: 'test',
101+
reachable: false,
102+
} as ClusterInfo
103+
render(<ClusterIAMRefreshHint cluster={cluster} className="test-class" />)
102104

103-
expect(screen.getByText(/Custom:/)).toBeInTheDocument()
105+
expect(screen.getByText('gcloud auth login')).toBeInTheDocument()
106+
})
104107

105-
rerender(
106-
<ClusterIAMRefreshHint
107-
cluster={{
108-
authMethod: 'exec',
109-
user: 'az-user',
110-
name: 'demo',
111-
errorType: 'auth',
112-
reachable: false,
113-
} as ClusterInfo}
114-
className="hint-class"
115-
label={null}
116-
/>,
117-
)
108+
it('does not render for non-exec auth', () => {
109+
const cluster = {
110+
authMethod: 'token',
111+
errorType: 'auth',
112+
reachable: false,
113+
} as ClusterInfo
114+
const { container } = render(<ClusterIAMRefreshHint cluster={cluster} className="test-class" />)
118115

119-
expect(screen.queryByText(/Login:/)).not.toBeInTheDocument()
120-
expect(screen.getByText('az login')).toBeInTheDocument()
116+
expect(container.firstChild).toBeNull()
121117
})
122118

123-
it('returns null when the cluster does not need or cannot infer refresh help', () => {
124-
const { container, rerender } = render(
125-
<ClusterIAMRefreshHint
126-
cluster={{
127-
authMethod: 'token',
128-
errorType: 'auth',
129-
reachable: false,
130-
} as ClusterInfo}
131-
className="hint-class"
132-
/>,
133-
)
119+
it('does not render for reachable cluster with valid token', () => {
120+
const cluster = {
121+
authMethod: 'exec',
122+
user: 'aws-user',
123+
name: 'test',
124+
reachable: true,
125+
} as ClusterInfo
126+
const { container } = render(<ClusterIAMRefreshHint cluster={cluster} className="test-class" />)
134127

135128
expect(container.firstChild).toBeNull()
129+
})
136130

137-
rerender(
138-
<ClusterIAMRefreshHint
139-
cluster={{
140-
authMethod: 'exec',
141-
user: 'custom-user',
142-
name: 'custom-cluster',
143-
errorType: 'auth',
144-
reachable: false,
145-
} as ClusterInfo}
146-
className="hint-class"
147-
/>,
148-
)
131+
it('does not render when no IAM hint is available', () => {
132+
const cluster = {
133+
authMethod: 'exec',
134+
user: 'unknown',
135+
name: 'test',
136+
errorType: 'auth',
137+
reachable: false,
138+
} as ClusterInfo
139+
const { container } = render(<ClusterIAMRefreshHint cluster={cluster} className="test-class" />)
149140

150141
expect(container.firstChild).toBeNull()
151142
})
143+
144+
it('renders custom label when provided', () => {
145+
const cluster = {
146+
authMethod: 'exec',
147+
user: 'az-user',
148+
name: 'test',
149+
errorType: 'auth',
150+
reachable: false,
151+
} as ClusterInfo
152+
render(<ClusterIAMRefreshHint cluster={cluster} className="test-class" label="Custom:" />)
153+
154+
expect(screen.getByText(/Custom:/)).toBeInTheDocument()
155+
})
156+
157+
it('renders without label when label is null', () => {
158+
const cluster = {
159+
authMethod: 'exec',
160+
user: 'az-user',
161+
name: 'test',
162+
errorType: 'auth',
163+
reachable: false,
164+
} as ClusterInfo
165+
render(<ClusterIAMRefreshHint cluster={cluster} className="test-class" label={null} />)
166+
167+
expect(screen.queryByText(/Login:/)).not.toBeInTheDocument()
168+
expect(screen.getByText('az login')).toBeInTheDocument()
169+
})
170+
171+
it('includes copy button', () => {
172+
const cluster = {
173+
authMethod: 'exec',
174+
user: 'aws-user',
175+
name: 'test',
176+
errorType: 'auth',
177+
reachable: false,
178+
} as ClusterInfo
179+
render(<ClusterIAMRefreshHint cluster={cluster} className="test-class" />)
180+
181+
expect(screen.getByLabelText('Copy command to clipboard')).toBeInTheDocument()
182+
})
152183
})

0 commit comments

Comments
 (0)