Skip to content

Commit a96e334

Browse files
committed
refactor(test): use credential builders and shared fixtures
- Use validCredentials(), invalidCredentials(), credentialsWithHost(), and credentialsWithPort() helpers in Playwright tests - Extract shared algorithm test fixtures to reduce inline definitions - Use it.each pattern for parametrized test cases
1 parent df74882 commit a96e334

File tree

5 files changed

+156
-289
lines changed

5 files changed

+156
-289
lines changed

tests/playwright/websocket-async-auth-v2.test.js

Lines changed: 9 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ import {
2121
fillFormDirectly,
2222
executeCommandsWithExpectedOutput,
2323
executeCommandList,
24-
getTerminalContent
24+
getTerminalContent,
25+
validCredentials,
26+
invalidCredentials,
27+
credentialsWithHost
2528
} from './v2-helpers.js'
2629

2730
test.describe('V2 Async Error Recovery and Edge Cases', () => {
@@ -52,12 +55,7 @@ test.describe('V2 Async/Await Modal Login Authentication', () => {
5255

5356
test('should handle async connect with valid credentials (V2)', async ({ page }) => {
5457
// Use shared helper to connect
55-
await connectV2(page, {
56-
host: TEST_CONFIG.sshHost,
57-
port: TEST_CONFIG.sshPort,
58-
username: TEST_CONFIG.validUsername,
59-
password: TEST_CONFIG.validPassword
60-
})
58+
await connectV2(page, validCredentials())
6159

6260
// Verify successful async connection with V2
6361
await waitForV2Connection(page)
@@ -68,12 +66,7 @@ test.describe('V2 Async/Await Modal Login Authentication', () => {
6866

6967
test('should handle async authentication error properly (V2)', async ({ page }) => {
7068
// Use shared helper to connect with invalid credentials
71-
await connectV2(page, {
72-
host: TEST_CONFIG.sshHost,
73-
port: TEST_CONFIG.sshPort,
74-
username: TEST_CONFIG.invalidUsername,
75-
password: TEST_CONFIG.invalidPassword
76-
})
69+
await connectV2(page, invalidCredentials())
7770

7871
// Use shared helper to check for errors
7972
const errorFound = await checkForV2AuthError(page)
@@ -88,12 +81,7 @@ test.describe('V2 Async/Await Modal Login Authentication', () => {
8881

8982
test('should handle async connection error for non-existent host (V2)', async ({ page }) => {
9083
// Use shared helper with non-existent host
91-
await connectV2(page, {
92-
host: TEST_CONFIG.nonExistentHost,
93-
port: TEST_CONFIG.sshPort,
94-
username: TEST_CONFIG.validUsername,
95-
password: TEST_CONFIG.validPassword
96-
})
84+
await connectV2(page, credentialsWithHost(TEST_CONFIG.nonExistentHost))
9785

9886
// V2 should handle network errors asynchronously
9987
await expect(
@@ -103,12 +91,7 @@ test.describe('V2 Async/Await Modal Login Authentication', () => {
10391

10492
test('should handle async shell creation and terminal operations (V2)', async ({ page }) => {
10593
// Connect and wait for terminal
106-
await connectAndWaitForTerminal(page, {
107-
host: TEST_CONFIG.sshHost,
108-
port: TEST_CONFIG.sshPort,
109-
username: TEST_CONFIG.validUsername,
110-
password: TEST_CONFIG.validPassword
111-
})
94+
await connectAndWaitForTerminal(page, validCredentials())
11295

11396
// Test multiple async terminal operations
11497
const commands = [
@@ -129,12 +112,7 @@ test.describe('V2 Async/Await Modal Login Authentication', () => {
129112

130113
test('should handle terminal resize with async operations (V2)', async ({ page }) => {
131114
// Connect using helper
132-
await connectAndWaitForTerminal(page, {
133-
host: TEST_CONFIG.sshHost,
134-
port: TEST_CONFIG.sshPort,
135-
username: TEST_CONFIG.validUsername,
136-
password: TEST_CONFIG.validPassword
137-
})
115+
await connectAndWaitForTerminal(page, validCredentials())
138116

139117
// Get initial terminal size
140118
await executeV2Command(page, 'stty size')

tests/playwright/websocket-auth-v2.test.js

Lines changed: 9 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ import {
1717
connectWithBasicAuth,
1818
executeAndVerifyCommand,
1919
connectAndWaitForTerminal,
20-
fillFormDirectly
20+
fillFormDirectly,
21+
validCredentials,
22+
invalidCredentials,
23+
credentialsWithPort
2124
} from './v2-helpers.js'
2225

2326
test.describe('V2 WebSocket Interactive Authentication', () => {
@@ -27,25 +30,15 @@ test.describe('V2 WebSocket Interactive Authentication', () => {
2730

2831
test('should connect successfully with valid credentials', async ({ page }) => {
2932
// Use shared helper to connect and wait
30-
await connectAndWaitForTerminal(page, {
31-
host: TEST_CONFIG.sshHost,
32-
port: TEST_CONFIG.sshPort,
33-
username: TEST_CONFIG.validUsername,
34-
password: TEST_CONFIG.validPassword
35-
})
33+
await connectAndWaitForTerminal(page, validCredentials())
3634

3735
// Verify terminal is functional
3836
await executeAndVerifyCommand(page, 'whoami', TEST_CONFIG.validUsername)
3937
})
4038

4139
test('should show error with invalid credentials', async ({ page }) => {
4240
// Use shared helper to connect
43-
await connectV2(page, {
44-
host: TEST_CONFIG.sshHost,
45-
port: TEST_CONFIG.sshPort,
46-
username: TEST_CONFIG.invalidUsername,
47-
password: TEST_CONFIG.invalidPassword
48-
})
41+
await connectV2(page, invalidCredentials())
4942

5043
// Use shared helper to check for errors
5144
const errorFound = await checkForV2AuthError(page)
@@ -60,25 +53,15 @@ test.describe('V2 WebSocket Interactive Authentication', () => {
6053

6154
test('should show connection error for wrong port', async ({ page }) => {
6255
// Use shared helper to connect with wrong port
63-
await connectV2(page, {
64-
host: TEST_CONFIG.sshHost,
65-
port: TEST_CONFIG.invalidPort,
66-
username: TEST_CONFIG.validUsername,
67-
password: TEST_CONFIG.validPassword
68-
})
56+
await connectV2(page, credentialsWithPort(TEST_CONFIG.invalidPort))
6957

7058
// V2 should show connection error
7159
await expect(page.locator('text=/Authentication failed|Connection refused|ECONNREFUSED/').first()).toBeVisible({ timeout: TIMEOUTS.DEFAULT })
7260
})
7361

7462
test('should handle page refresh gracefully', async ({ page }) => {
7563
// First, establish a connection
76-
await connectAndWaitForTerminal(page, {
77-
host: TEST_CONFIG.sshHost,
78-
port: TEST_CONFIG.sshPort,
79-
username: TEST_CONFIG.validUsername,
80-
password: TEST_CONFIG.validPassword
81-
})
64+
await connectAndWaitForTerminal(page, validCredentials())
8265

8366
// Disable beforeunload handler and refresh
8467
await page.evaluate(() => {
@@ -91,12 +74,7 @@ test.describe('V2 WebSocket Interactive Authentication', () => {
9174
await expect(page.locator('[name="username"]')).toBeVisible()
9275

9376
// Re-authenticate
94-
await connectAndWaitForTerminal(page, {
95-
host: TEST_CONFIG.sshHost,
96-
port: TEST_CONFIG.sshPort,
97-
username: TEST_CONFIG.validUsername,
98-
password: TEST_CONFIG.validPassword
99-
})
77+
await connectAndWaitForTerminal(page, validCredentials())
10078
})
10179
})
10280

tests/unit/services/ssh/algorithm-analyzer.vitest.ts

Lines changed: 30 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ import {
1515
createLegacyServerSet,
1616
createModernServerSet,
1717
createSetWithCategory,
18+
createModernOnlyClientSet,
19+
createMinimalLegacyServerSet,
20+
createStrictServerSet,
21+
createUnknownServerSet,
22+
createModernCompatibleServerSet,
23+
createCompatibleClientSet,
24+
createModernClientSet,
1825
type AlgorithmSet
1926
} from './algorithm-test-fixtures.js'
2027

@@ -148,21 +155,8 @@ describe('analyzeAlgorithms', () => {
148155

149156
describe('preset suggestion', () => {
150157
it('suggests legacy preset for servers with only legacy algorithms', () => {
151-
// Modern client with no overlap with legacy server
152-
const client: AlgorithmSet = {
153-
kex: ['curve25519-sha256'],
154-
serverHostKey: ['ssh-ed25519'],
155-
cipher: ['aes256-gcm@openssh.com'],
156-
mac: ['hmac-sha2-256'],
157-
compress: ['none']
158-
}
159-
const server: AlgorithmSet = {
160-
kex: ['diffie-hellman-group14-sha1'],
161-
serverHostKey: ['ssh-rsa'],
162-
cipher: ['aes128-cbc'],
163-
mac: ['hmac-sha1'],
164-
compress: ['none']
165-
}
158+
const client = createModernOnlyClientSet()
159+
const server = createMinimalLegacyServerSet()
166160

167161
const analysis = analyzeAlgorithms(client, server)
168162
expect(analysis.suggestedPreset).toBe('legacy')
@@ -179,20 +173,8 @@ describe('analyzeAlgorithms', () => {
179173

180174
describe('env var suggestions', () => {
181175
it('generates suggestions for mismatched categories', () => {
182-
const client: AlgorithmSet = {
183-
kex: ['curve25519-sha256'],
184-
serverHostKey: ['ssh-ed25519'],
185-
cipher: ['aes256-gcm@openssh.com'],
186-
mac: ['hmac-sha2-256'],
187-
compress: ['none']
188-
}
189-
const server: AlgorithmSet = {
190-
kex: ['diffie-hellman-group14-sha1'],
191-
serverHostKey: ['ssh-rsa'],
192-
cipher: ['aes128-cbc'],
193-
mac: ['hmac-sha1'],
194-
compress: ['none']
195-
}
176+
const client = createModernOnlyClientSet()
177+
const server = createMinimalLegacyServerSet()
196178

197179
const analysis = analyzeAlgorithms(client, server)
198180

@@ -203,20 +185,12 @@ describe('analyzeAlgorithms', () => {
203185
})
204186

205187
it('does not generate suggestions for categories with matches', () => {
188+
// Client with KEX fallback that matches server
206189
const client: AlgorithmSet = {
207-
kex: ['curve25519-sha256', 'diffie-hellman-group14-sha1'],
208-
serverHostKey: ['ssh-ed25519'],
209-
cipher: ['aes256-gcm@openssh.com'],
210-
mac: ['hmac-sha2-256'],
211-
compress: ['none']
212-
}
213-
const server: AlgorithmSet = {
214-
kex: ['diffie-hellman-group14-sha1'],
215-
serverHostKey: ['ssh-rsa'],
216-
cipher: ['aes128-cbc'],
217-
mac: ['hmac-sha1'],
218-
compress: ['none']
190+
...createModernOnlyClientSet(),
191+
kex: ['curve25519-sha256', 'diffie-hellman-group14-sha1']
219192
}
193+
const server = createMinimalLegacyServerSet()
220194

221195
const analysis = analyzeAlgorithms(client, server)
222196

@@ -235,61 +209,18 @@ describe('analyzeAlgorithms', () => {
235209
})
236210
})
237211

238-
describe('suggestPreset', () => {
239-
it('suggests strict preset for strict-compatible servers', () => {
240-
const server: AlgorithmSet = {
241-
kex: ['ecdh-sha2-nistp256', 'curve25519-sha256'],
242-
serverHostKey: ['ecdsa-sha2-nistp256', 'ssh-ed25519'],
243-
cipher: ['aes256-gcm@openssh.com', 'aes128-gcm@openssh.com'],
244-
mac: ['hmac-sha2-256', 'hmac-sha2-512'],
245-
compress: ['none']
246-
}
247-
248-
expect(suggestPreset(server)).toBe('strict')
249-
})
250-
251-
it('suggests modern preset for servers that need modern but not strict', () => {
252-
// Server only supports algorithms in modern preset but NOT in strict preset
253-
const server: AlgorithmSet = {
254-
kex: ['ecdh-sha2-nistp384'], // In modern, NOT in strict
255-
serverHostKey: ['ecdsa-sha2-nistp384'], // In modern, NOT in strict
256-
cipher: ['aes128-ctr'], // In modern, NOT in strict
257-
mac: ['hmac-sha2-512'], // In modern, NOT in strict
258-
compress: ['none']
259-
}
260-
261-
expect(suggestPreset(server)).toBe('modern')
262-
})
263-
264-
it('suggests legacy preset for legacy servers', () => {
265-
const server: AlgorithmSet = {
266-
kex: ['diffie-hellman-group14-sha1', 'diffie-hellman-group1-sha1'],
267-
serverHostKey: ['ssh-rsa', 'ssh-dss'],
268-
cipher: ['aes128-cbc', '3des-cbc'],
269-
mac: ['hmac-sha1', 'hmac-md5'],
270-
compress: ['none']
271-
}
272-
273-
expect(suggestPreset(server)).toBe('legacy')
274-
})
275-
276-
it('returns null for servers with completely incompatible algorithms', () => {
277-
const server: AlgorithmSet = {
278-
kex: ['unknown-kex-algorithm'],
279-
serverHostKey: ['unknown-hostkey'],
280-
cipher: ['unknown-cipher'],
281-
mac: ['unknown-mac'],
282-
compress: ['none']
283-
}
284-
285-
expect(suggestPreset(server)).toBeNull()
286-
})
287-
288-
it('handles empty server algorithm set', () => {
289-
const server = createEmptyAlgorithmSet()
212+
// Test cases for suggestPreset function
213+
const PRESET_TEST_CASES = [
214+
{ name: 'strict-compatible server', createServer: createStrictServerSet, expected: 'strict' },
215+
{ name: 'modern-compatible server', createServer: createModernCompatibleServerSet, expected: 'modern' },
216+
{ name: 'legacy server', createServer: createLegacyServerSet, expected: 'legacy' },
217+
{ name: 'unknown server', createServer: createUnknownServerSet, expected: null },
218+
{ name: 'empty server', createServer: createEmptyAlgorithmSet, expected: 'strict' }
219+
] as const
290220

291-
// Empty set should match any preset since there are no requirements
292-
expect(suggestPreset(server)).toBe('strict')
221+
describe('suggestPreset', () => {
222+
it.each(PRESET_TEST_CASES)('returns $expected for $name', ({ createServer, expected }) => {
223+
expect(suggestPreset(createServer())).toBe(expected)
293224
})
294225
})
295226

@@ -347,20 +278,8 @@ describe('generateEnvVarSuggestions', () => {
347278

348279
describe('Integration: realistic algorithm mismatch scenarios', () => {
349280
it('analyzes modern client vs legacy server', () => {
350-
const client: AlgorithmSet = {
351-
kex: ['curve25519-sha256', 'ecdh-sha2-nistp256'],
352-
serverHostKey: ['ssh-ed25519', 'ecdsa-sha2-nistp256'],
353-
cipher: ['aes256-gcm@openssh.com', 'aes128-gcm@openssh.com'],
354-
mac: ['hmac-sha2-256-etm@openssh.com', 'hmac-sha2-256'],
355-
compress: ['none', 'zlib@openssh.com']
356-
}
357-
const server: AlgorithmSet = {
358-
kex: ['diffie-hellman-group14-sha1'],
359-
serverHostKey: ['ssh-rsa'],
360-
cipher: ['aes128-cbc', '3des-cbc'],
361-
mac: ['hmac-sha1'],
362-
compress: ['none']
363-
}
281+
const client = createModernClientSet()
282+
const server = createMinimalLegacyServerSet()
364283

365284
const analysis = analyzeAlgorithms(client, server)
366285

@@ -381,20 +300,8 @@ describe('Integration: realistic algorithm mismatch scenarios', () => {
381300
})
382301

383302
it('analyzes compatible client and server', () => {
384-
const client: AlgorithmSet = {
385-
kex: ['curve25519-sha256', 'ecdh-sha2-nistp256', 'diffie-hellman-group14-sha1'],
386-
serverHostKey: ['ssh-ed25519', 'ssh-rsa'],
387-
cipher: ['aes256-gcm@openssh.com', 'aes128-cbc'],
388-
mac: ['hmac-sha2-256', 'hmac-sha1'],
389-
compress: ['none']
390-
}
391-
const server: AlgorithmSet = {
392-
kex: ['diffie-hellman-group14-sha1'],
393-
serverHostKey: ['ssh-rsa'],
394-
cipher: ['aes128-cbc'],
395-
mac: ['hmac-sha1'],
396-
compress: ['none']
397-
}
303+
const client = createCompatibleClientSet()
304+
const server = createMinimalLegacyServerSet()
398305

399306
const analysis = analyzeAlgorithms(client, server)
400307

0 commit comments

Comments
 (0)