|
2 | 2 | import { it, afterEach, vi, expect } from "vitest"
|
3 | 3 | import { SSHConfig } from "./sshConfig"
|
4 | 4 |
|
5 |
| -const sshFilePath = "~/.config/ssh" |
| 5 | +// This is not the usual path to ~/.ssh/config, but |
| 6 | +// setting it to a different path makes it easier to test |
| 7 | +// and makes mistakes abundantly clear. |
| 8 | +const sshFilePath = "/Path/To/UserHomeDir/.sshConfigDir/sshConfigFile" |
| 9 | +const sshTempFilePathExpr = `^/Path/To/UserHomeDir/.sshConfigDir/.sshConfigFile.vscode-coder-tmp.[a-z0-9]+$` |
6 | 10 |
|
7 | 11 | const mockFileSystem = {
|
8 | 12 | mkdir: vi.fn(),
|
@@ -42,11 +46,14 @@ Host coder-vscode--*
|
42 | 46 |
|
43 | 47 | expect(mockFileSystem.readFile).toBeCalledWith(sshFilePath, expect.anything())
|
44 | 48 | expect(mockFileSystem.writeFile).toBeCalledWith(
|
45 |
| - expect.stringContaining(sshFilePath), |
| 49 | + expect.stringMatching(sshTempFilePathExpr), |
46 | 50 | expectedOutput,
|
47 |
| - expect.anything(), |
| 51 | + expect.objectContaining({ |
| 52 | + encoding: "utf-8", |
| 53 | + mode: 0o600, // Default mode for new files. |
| 54 | + }), |
48 | 55 | )
|
49 |
| - expect(mockFileSystem.rename).toBeCalledWith(expect.stringContaining(sshFilePath + "."), sshFilePath) |
| 56 | + expect(mockFileSystem.rename).toBeCalledWith(expect.stringMatching(sshTempFilePathExpr), sshFilePath) |
50 | 57 | })
|
51 | 58 |
|
52 | 59 | it("creates a new file and adds the config", async () => {
|
@@ -75,11 +82,14 @@ Host coder-vscode.dev.coder.com--*
|
75 | 82 |
|
76 | 83 | expect(mockFileSystem.readFile).toBeCalledWith(sshFilePath, expect.anything())
|
77 | 84 | expect(mockFileSystem.writeFile).toBeCalledWith(
|
78 |
| - expect.stringContaining(sshFilePath), |
| 85 | + expect.stringMatching(sshTempFilePathExpr), |
79 | 86 | expectedOutput,
|
80 |
| - expect.anything(), |
| 87 | + expect.objectContaining({ |
| 88 | + encoding: "utf-8", |
| 89 | + mode: 0o600, // Default mode for new files. |
| 90 | + }), |
81 | 91 | )
|
82 |
| - expect(mockFileSystem.rename).toBeCalledWith(expect.stringContaining(sshFilePath + "."), sshFilePath) |
| 92 | + expect(mockFileSystem.rename).toBeCalledWith(expect.stringMatching(sshTempFilePathExpr), sshFilePath) |
83 | 93 | })
|
84 | 94 |
|
85 | 95 | it("adds a new coder config in an existent SSH configuration", async () => {
|
@@ -115,11 +125,11 @@ Host coder-vscode.dev.coder.com--*
|
115 | 125 | UserKnownHostsFile /dev/null
|
116 | 126 | # --- END CODER VSCODE dev.coder.com ---`
|
117 | 127 |
|
118 |
| - expect(mockFileSystem.writeFile).toBeCalledWith(expect.stringContaining(sshFilePath), expectedOutput, { |
| 128 | + expect(mockFileSystem.writeFile).toBeCalledWith(expect.stringMatching(sshTempFilePathExpr), expectedOutput, { |
119 | 129 | encoding: "utf-8",
|
120 | 130 | mode: 0o644,
|
121 | 131 | })
|
122 |
| - expect(mockFileSystem.rename).toBeCalledWith(expect.stringContaining(sshFilePath + "."), sshFilePath) |
| 132 | + expect(mockFileSystem.rename).toBeCalledWith(expect.stringMatching(sshTempFilePathExpr), sshFilePath) |
123 | 133 | })
|
124 | 134 |
|
125 | 135 | it("updates an existent coder config", async () => {
|
@@ -181,11 +191,11 @@ Host coder-vscode.dev-updated.coder.com--*
|
181 | 191 | Host *
|
182 | 192 | SetEnv TEST=1`
|
183 | 193 |
|
184 |
| - expect(mockFileSystem.writeFile).toBeCalledWith(expect.stringContaining(sshFilePath), expectedOutput, { |
| 194 | + expect(mockFileSystem.writeFile).toBeCalledWith(expect.stringMatching(sshTempFilePathExpr), expectedOutput, { |
185 | 195 | encoding: "utf-8",
|
186 | 196 | mode: 0o644,
|
187 | 197 | })
|
188 |
| - expect(mockFileSystem.rename).toBeCalledWith(expect.stringContaining(sshFilePath + "."), sshFilePath) |
| 198 | + expect(mockFileSystem.rename).toBeCalledWith(expect.stringMatching(sshTempFilePathExpr), sshFilePath) |
189 | 199 | })
|
190 | 200 |
|
191 | 201 | it("does not remove deployment-unaware SSH config and adds the new one", async () => {
|
@@ -228,11 +238,11 @@ Host coder-vscode.dev.coder.com--*
|
228 | 238 | UserKnownHostsFile /dev/null
|
229 | 239 | # --- END CODER VSCODE dev.coder.com ---`
|
230 | 240 |
|
231 |
| - expect(mockFileSystem.writeFile).toBeCalledWith(expect.stringContaining(sshFilePath), expectedOutput, { |
| 241 | + expect(mockFileSystem.writeFile).toBeCalledWith(expect.stringMatching(sshTempFilePathExpr), expectedOutput, { |
232 | 242 | encoding: "utf-8",
|
233 | 243 | mode: 0o644,
|
234 | 244 | })
|
235 |
| - expect(mockFileSystem.rename).toBeCalledWith(expect.stringContaining(sshFilePath + "."), sshFilePath) |
| 245 | + expect(mockFileSystem.rename).toBeCalledWith(expect.stringMatching(sshTempFilePathExpr), sshFilePath) |
236 | 246 | })
|
237 | 247 |
|
238 | 248 | it("it does not remove a user-added block that only matches the host of an old coder SSH config", async () => {
|
@@ -264,11 +274,11 @@ Host coder-vscode.dev.coder.com--*
|
264 | 274 | UserKnownHostsFile /dev/null
|
265 | 275 | # --- END CODER VSCODE dev.coder.com ---`
|
266 | 276 |
|
267 |
| - expect(mockFileSystem.writeFile).toBeCalledWith(expect.stringContaining(sshFilePath), expectedOutput, { |
| 277 | + expect(mockFileSystem.writeFile).toBeCalledWith(expect.stringMatching(sshTempFilePathExpr), expectedOutput, { |
268 | 278 | encoding: "utf-8",
|
269 | 279 | mode: 0o644,
|
270 | 280 | })
|
271 |
| - expect(mockFileSystem.rename).toBeCalledWith(expect.stringContaining(sshFilePath + "."), sshFilePath) |
| 281 | + expect(mockFileSystem.rename).toBeCalledWith(expect.stringMatching(sshTempFilePathExpr), sshFilePath) |
272 | 282 | })
|
273 | 283 |
|
274 | 284 | it("throws an error if there is a missing end block", async () => {
|
@@ -540,11 +550,11 @@ Host afterconfig
|
540 | 550 | LogLevel: "ERROR",
|
541 | 551 | })
|
542 | 552 |
|
543 |
| - expect(mockFileSystem.writeFile).toBeCalledWith(expect.stringContaining(sshFilePath), expectedOutput, { |
| 553 | + expect(mockFileSystem.writeFile).toBeCalledWith(expect.stringMatching(sshTempFilePathExpr), expectedOutput, { |
544 | 554 | encoding: "utf-8",
|
545 | 555 | mode: 0o644,
|
546 | 556 | })
|
547 |
| - expect(mockFileSystem.rename).toBeCalledWith(expect.stringContaining(sshFilePath + "."), sshFilePath) |
| 557 | + expect(mockFileSystem.rename).toBeCalledWith(expect.stringMatching(sshTempFilePathExpr), sshFilePath) |
548 | 558 | })
|
549 | 559 |
|
550 | 560 | it("override values", async () => {
|
@@ -588,9 +598,12 @@ Host coder-vscode.dev.coder.com--*
|
588 | 598 |
|
589 | 599 | expect(mockFileSystem.readFile).toBeCalledWith(sshFilePath, expect.anything())
|
590 | 600 | expect(mockFileSystem.writeFile).toBeCalledWith(
|
591 |
| - expect.stringContaining(sshFilePath), |
| 601 | + expect.stringMatching(sshTempFilePathExpr), |
592 | 602 | expectedOutput,
|
593 |
| - expect.anything(), |
| 603 | + expect.objectContaining({ |
| 604 | + encoding: "utf-8", |
| 605 | + mode: 0o600, // Default mode for new files. |
| 606 | + }), |
594 | 607 | )
|
595 |
| - expect(mockFileSystem.rename).toBeCalledWith(expect.stringContaining(sshFilePath + "."), sshFilePath) |
| 608 | + expect(mockFileSystem.rename).toBeCalledWith(expect.stringMatching(sshTempFilePathExpr), sshFilePath) |
596 | 609 | })
|
0 commit comments