Skip to content

Commit e120bac

Browse files
More test cleanup
1 parent ddcb14e commit e120bac

4 files changed

Lines changed: 37 additions & 127 deletions

File tree

src/cloud/auth.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ import { trackCloudSignIn } from "../utils/telemetry"
1919
import { ApiService } from "./api"
2020

2121
export const AUTH_PROVIDER_ID = "fastapi-vscode"
22-
const NAME = "FastAPI Cloud"
22+
export const NAME = "FastAPI Cloud"
2323
const AUTH_POLL_INTERVAL_MS = 3000
2424
const SECRET_STORAGE_KEY = "fastapi-cloud-access-token"
25-
const SESSION_ID = "fastapi-cloud-session"
26-
const ACCOUNT_ID = "fastapi-cloud-account"
25+
export const SESSION_ID = "fastapi-cloud-session"
26+
export const ACCOUNT_ID = "fastapi-cloud-account"
2727

2828
interface AuthConfig {
2929
access_token: string

src/test/cloud/auth.test.ts

Lines changed: 7 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import * as assert from "node:assert"
22
import sinon from "sinon"
33
import * as vscode from "vscode"
4-
import { CloudAuthenticationProvider, isTokenExpired } from "../../cloud/auth"
4+
import {
5+
CloudAuthenticationProvider,
6+
isTokenExpired,
7+
SESSION_ID,
8+
} from "../../cloud/auth"
59
import { mockResponse, stubFs } from "../testUtils"
610

711
function createJwtToken(payload: Record<string, unknown>): string {
@@ -253,7 +257,7 @@ suite("cloud/auth", () => {
253257
const fired = sinon.stub()
254258
provider.onDidChangeSessions(fired)
255259

256-
await provider.removeSession("fastapi-cloud-session")
260+
await provider.removeSession(SESSION_ID)
257261

258262
assert.ok(fsStub.fake.delete.calledOnce)
259263
const removeEvent = fired.args.find(
@@ -263,37 +267,7 @@ suite("cloud/auth", () => {
263267
removeEvent,
264268
"should fire onDidChangeSessions with removed session",
265269
)
266-
assert.strictEqual(
267-
removeEvent[0].removed[0].id,
268-
"fastapi-cloud-session",
269-
)
270-
271-
await provider.dispose()
272-
})
273-
274-
test("handles file not found gracefully", async () => {
275-
fsStub.fake.readFile.rejects(new Error("File not found"))
276-
277-
const { provider } = createProvider()
278-
await provider.removeSession("nonexistent")
279-
280-
await provider.dispose()
281-
})
282-
283-
test("handles delete failure gracefully", async () => {
284-
const token = validToken()
285-
fsStub.fake.readFile.resolves(
286-
Buffer.from(JSON.stringify({ access_token: token })),
287-
)
288-
sinon
289-
.stub(globalThis, "fetch")
290-
.resolves(
291-
mockResponse({ email: "test@example.com", full_name: "Test" }),
292-
)
293-
fsStub.fake.delete.rejects(new Error("Permission denied"))
294-
295-
const { provider } = createProvider()
296-
await provider.removeSession("fastapi-cloud-session")
270+
assert.strictEqual(removeEvent[0].removed[0].id, SESSION_ID)
297271

298272
await provider.dispose()
299273
})
@@ -334,15 +308,6 @@ suite("cloud/auth", () => {
334308

335309
await provider.dispose()
336310
})
337-
338-
test("works when no sessions exist", async () => {
339-
fsStub.fake.readFile.rejects(new Error("File not found"))
340-
341-
const { provider } = createProvider()
342-
await provider.signOut()
343-
344-
await provider.dispose()
345-
})
346311
})
347312

348313
suite("createSession", () => {

src/test/cloud/cloudController.test.ts

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as assert from "node:assert"
22
import sinon from "sinon"
33
import * as vscode from "vscode"
44
import { ApiService } from "../../cloud/api"
5+
import { ACCOUNT_ID, NAME, SESSION_ID } from "../../cloud/auth"
56
import { CloudController } from "../../cloud/cloudController"
67
import { ConfigService } from "../../cloud/config"
78
import type { App, Team } from "../../cloud/types"
@@ -20,8 +21,8 @@ function createStatusBarStub() {
2021

2122
const mockSession = {
2223
accessToken: "test_token",
23-
id: "fastapi-cloud-session",
24-
account: { id: "fastapi-cloud-account", label: "FastAPI Cloud" },
24+
id: SESSION_ID,
25+
account: { id: ACCOUNT_ID, label: NAME },
2526
scopes: [],
2627
} as vscode.AuthenticationSession
2728

@@ -128,11 +129,6 @@ suite("cloud/cloudController", () => {
128129
const deps = createController()
129130
await initializeWithApp(deps)
130131

131-
// Restore isLoggedIn so showMenu can re-stub it
132-
;(vscode.authentication.getSession as sinon.SinonStub).resolves(
133-
mockSession as any,
134-
)
135-
136132
const quickPickStub = sinon
137133
.stub(vscode.window, "showQuickPick")
138134
.resolves(undefined)
@@ -151,9 +147,6 @@ suite("cloud/cloudController", () => {
151147
test("opens app URL when open selected", async () => {
152148
const deps = createController()
153149
await initializeWithApp(deps)
154-
;(vscode.authentication.getSession as sinon.SinonStub).resolves(
155-
mockSession as any,
156-
)
157150

158151
sinon
159152
.stub(vscode.window, "showQuickPick")
@@ -170,9 +163,6 @@ suite("cloud/cloudController", () => {
170163
test("opens dashboard when dashboard selected", async () => {
171164
const deps = createController()
172165
await initializeWithApp(deps)
173-
;(vscode.authentication.getSession as sinon.SinonStub).resolves(
174-
mockSession as any,
175-
)
176166

177167
sinon
178168
.stub(vscode.window, "showQuickPick")
@@ -189,9 +179,6 @@ suite("cloud/cloudController", () => {
189179
test("shows more menu when more selected", async () => {
190180
const deps = createController()
191181
await initializeWithApp(deps)
192-
;(vscode.authentication.getSession as sinon.SinonStub).resolves(
193-
mockSession as any,
194-
)
195182

196183
const quickPickStub = sinon.stub(vscode.window, "showQuickPick")
197184
// First call: main menu selects "more"
@@ -211,9 +198,6 @@ suite("cloud/cloudController", () => {
211198
test("unlinks project when unlink selected", async () => {
212199
const deps = createController()
213200
await initializeWithApp(deps)
214-
;(vscode.authentication.getSession as sinon.SinonStub).resolves(
215-
mockSession as any,
216-
)
217201

218202
const quickPickStub = sinon.stub(vscode.window, "showQuickPick")
219203
quickPickStub.onFirstCall().resolves({ label: "", id: "more" } as any)
@@ -234,9 +218,6 @@ suite("cloud/cloudController", () => {
234218
test("signs out when signout selected", async () => {
235219
const deps = createController()
236220
await initializeWithApp(deps)
237-
;(vscode.authentication.getSession as sinon.SinonStub).resolves(
238-
mockSession as any,
239-
)
240221

241222
const quickPickStub = sinon.stub(vscode.window, "showQuickPick")
242223
quickPickStub.onFirstCall().resolves({ label: "", id: "more" } as any)
@@ -352,14 +333,14 @@ suite("cloud/cloudController", () => {
352333
})
353334

354335
suite("linkProject", () => {
355-
test("does nothing without workspace root", async () => {
336+
test("shows error without workspace root", async () => {
356337
const deps = createController()
357338

358-
const writeStub = sinon.stub(deps.configService, "writeConfig").resolves()
339+
const errorStub = sinon.stub(vscode.window, "showErrorMessage")
359340

360341
await deps.controller.linkProject()
361342

362-
assert.ok(!writeStub.called)
343+
assert.ok(errorStub.calledOnceWith("No workspace folder open"))
363344

364345
dispose(deps)
365346
})
@@ -507,9 +488,25 @@ suite("cloud/cloudController", () => {
507488
})
508489

509490
suite("dispose", () => {
510-
test("does not throw", () => {
491+
test("disposes session listener and status bar", () => {
511492
const deps = createController()
493+
const listenerDisposable = { dispose: sinon.stub() }
494+
const original = vscode.authentication.onDidChangeSessions
495+
Object.defineProperty(vscode.authentication, "onDidChangeSessions", {
496+
value: () => listenerDisposable,
497+
configurable: true,
498+
})
499+
500+
deps.controller.showStatusBar()
512501
deps.controller.dispose()
502+
503+
assert.ok(listenerDisposable.dispose.calledOnce)
504+
assert.ok((deps.statusBar.dispose as sinon.SinonStub).calledOnce)
505+
506+
Object.defineProperty(vscode.authentication, "onDidChangeSessions", {
507+
value: original,
508+
configurable: true,
509+
})
513510
})
514511
})
515512
})

src/test/cloud/config.test.ts

Lines changed: 4 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -6,49 +6,42 @@ import { stubFs } from "../testUtils"
66

77
suite("cloud/config", () => {
88
let fsStub: ReturnType<typeof stubFs>
9+
let config: ConfigService
10+
const workspaceRoot = vscode.Uri.file("/tmp/test-workspace")
911

1012
setup(() => {
1113
fsStub = stubFs()
14+
config = new ConfigService()
1215
})
1316

1417
teardown(() => {
18+
config.dispose()
1519
fsStub.restore()
1620
sinon.restore()
1721
})
1822

1923
suite("getConfig", () => {
2024
test("returns parsed config when file exists", async () => {
21-
const config = new ConfigService()
22-
const workspaceRoot = vscode.Uri.file("/tmp/test-workspace")
2325
const configData = { app_id: "app-123", team_id: "team-456" }
2426

2527
fsStub.fake.readFile.resolves(Buffer.from(JSON.stringify(configData)))
2628

2729
const result = await config.getConfig(workspaceRoot)
2830

2931
assert.deepStrictEqual(result, configData)
30-
31-
config.dispose()
3232
})
3333

3434
test("returns null when file does not exist", async () => {
35-
const config = new ConfigService()
36-
const workspaceRoot = vscode.Uri.file("/tmp/test-workspace")
37-
3835
fsStub.fake.readFile.rejects(new Error("File not found"))
3936

4037
const result = await config.getConfig(workspaceRoot)
4138

4239
assert.strictEqual(result, null)
43-
44-
config.dispose()
4540
})
4641
})
4742

4843
suite("writeConfig", () => {
4944
test("writes config, readme, and gitignore", async () => {
50-
const config = new ConfigService()
51-
const workspaceRoot = vscode.Uri.file("/tmp/test-workspace")
5245
const configData = { app_id: "app-123", team_id: "team-456" }
5346

5447
fsStub.fake.createDirectory.resolves()
@@ -88,30 +81,11 @@ suite("cloud/config", () => {
8881
gitignoreCall.args[1] as Uint8Array,
8982
).toString()
9083
assert.strictEqual(gitignoreContent, "*")
91-
92-
config.dispose()
93-
})
94-
95-
test("does not throw on write failure", async () => {
96-
const config = new ConfigService()
97-
const workspaceRoot = vscode.Uri.file("/tmp/test-workspace")
98-
99-
fsStub.fake.createDirectory.rejects(new Error("Permission denied"))
100-
101-
await config.writeConfig(workspaceRoot, {
102-
app_id: "a",
103-
team_id: "t",
104-
})
105-
106-
config.dispose()
10784
})
10885
})
10986

11087
suite("deleteConfig", () => {
11188
test("deletes config directory recursively", async () => {
112-
const config = new ConfigService()
113-
const workspaceRoot = vscode.Uri.file("/tmp/test-workspace")
114-
11589
fsStub.fake.delete.resolves()
11690

11791
await config.deleteConfig(workspaceRoot)
@@ -120,27 +94,11 @@ suite("cloud/config", () => {
12094
const [uri, options] = fsStub.fake.delete.firstCall.args
12195
assert.ok((uri as vscode.Uri).path.endsWith(".fastapicloud"))
12296
assert.deepStrictEqual(options, { recursive: true })
123-
124-
config.dispose()
125-
})
126-
127-
test("does not throw when directory does not exist", async () => {
128-
const config = new ConfigService()
129-
const workspaceRoot = vscode.Uri.file("/tmp/test-workspace")
130-
131-
fsStub.fake.delete.rejects(new Error("Not found"))
132-
133-
await config.deleteConfig(workspaceRoot)
134-
135-
config.dispose()
13697
})
13798
})
13899

139100
suite("startWatching", () => {
140101
test("creates file system watcher", () => {
141-
const config = new ConfigService()
142-
const workspaceRoot = vscode.Uri.file("/tmp/test-workspace")
143-
144102
const mockWatcher = {
145103
onDidChange: sinon.stub(),
146104
onDidCreate: sinon.stub(),
@@ -157,16 +115,11 @@ suite("cloud/config", () => {
157115
assert.ok(mockWatcher.onDidChange.calledOnce)
158116
assert.ok(mockWatcher.onDidCreate.calledOnce)
159117
assert.ok(mockWatcher.onDidDelete.calledOnce)
160-
161-
config.dispose()
162118
})
163119
})
164120

165121
suite("dispose", () => {
166122
test("disposes file watcher", () => {
167-
const config = new ConfigService()
168-
const workspaceRoot = vscode.Uri.file("/tmp/test-workspace")
169-
170123
const mockWatcher = {
171124
onDidChange: sinon.stub(),
172125
onDidCreate: sinon.stub(),
@@ -183,10 +136,5 @@ suite("cloud/config", () => {
183136

184137
assert.ok(mockWatcher.dispose.calledOnce)
185138
})
186-
187-
test("dispose without watching does not throw", () => {
188-
const config = new ConfigService()
189-
config.dispose()
190-
})
191139
})
192140
})

0 commit comments

Comments
 (0)