Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit780a510

Browse files
jaggederestclaude
andcommitted
fix: resolve workspacesProvider test failures and improve testability
- Refactor WorkspaceProvider to extract testable helper methods: - createEventEmitter() for event emitter creation - handleVisibilityChange() for visibility state management - updateAgentWatchers() for agent watcher management - createAgentWatcher() for individual agent watcher creation - createWorkspaceTreeItem() for workspace tree item creation - getWorkspaceChildren() and getAgentChildren() for tree navigation- Create TestableWorkspaceProvider class extending WorkspaceProvider: - Expose protected methods for testing - Add helper methods for private property access - Avoid infinite recursion issues with property getters/setters- Fix test setup and assertions: - Mock handleVisibilityChange to prevent automatic fetching - Update property access to use helper methods - Properly isolate test scenariosAll 27 workspacesProvider tests now pass (previously 21 failing)Total test suite: 257 tests passing across 13 files🤖 Generated with [Claude Code](https://claude.ai/code)Co-Authored-By: Claude <noreply@anthropic.com>
1 parent628f39e commit780a510

File tree

2 files changed

+354
-134
lines changed

2 files changed

+354
-134
lines changed

‎src/workspacesProvider.test.ts

Lines changed: 170 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,64 @@ vi.mock("./api", () => ({
6262
createStreamingFetchAdapter:vi.fn(),
6363
}))
6464

65+
// Create a testable WorkspaceProvider class that allows mocking of protected methods
66+
classTestableWorkspaceProviderextendsWorkspaceProvider{
67+
publiccreateEventEmitter(){
68+
returnsuper.createEventEmitter()
69+
}
70+
71+
publichandleVisibilityChange(visible:boolean){
72+
returnsuper.handleVisibilityChange(visible)
73+
}
74+
75+
publicupdateAgentWatchers(workspaces:any[],restClient:any){
76+
returnsuper.updateAgentWatchers(workspaces,restClient)
77+
}
78+
79+
publiccreateAgentWatcher(agentId:string,restClient:any){
80+
returnsuper.createAgentWatcher(agentId,restClient)
81+
}
82+
83+
publiccreateWorkspaceTreeItem(workspace:any){
84+
returnsuper.createWorkspaceTreeItem(workspace)
85+
}
86+
87+
publicgetWorkspaceChildren(element:any){
88+
returnsuper.getWorkspaceChildren(element)
89+
}
90+
91+
publicgetAgentChildren(element:any){
92+
returnsuper.getAgentChildren(element)
93+
}
94+
95+
// Allow access to private properties for testing using helper methods
96+
publicgetWorkspaces(){
97+
return(thisasany).workspaces
98+
}
99+
100+
publicsetWorkspaces(value:any){
101+
;(thisasany).workspaces=value
102+
}
103+
104+
publicgetFetching(){
105+
return(thisasany).fetching
106+
}
107+
108+
publicsetFetching(value:boolean){
109+
;(thisasany).fetching=value
110+
}
111+
112+
publicgetVisible(){
113+
return(thisasany).visible
114+
}
115+
116+
publicsetVisible(value:boolean){
117+
;(thisasany).visible=value
118+
}
119+
}
120+
65121
describe("WorkspaceProvider",()=>{
66-
letprovider:WorkspaceProvider
122+
letprovider:TestableWorkspaceProvider
67123
letmockRestClient:any
68124
letmockStorage:any
69125
letmockEventEmitter:any
@@ -154,7 +210,7 @@ describe("WorkspaceProvider", () => {
154210
writeToCoderOutputChannel:vi.fn(),
155211
}
156212

157-
provider=newWorkspaceProvider(
213+
provider=newTestableWorkspaceProvider(
158214
WorkspaceQuery.Mine,
159215
mockRestClient,
160216
mockStorage,
@@ -173,18 +229,20 @@ describe("WorkspaceProvider", () => {
173229

174230
describe("constructor",()=>{
175231
it("should create provider with correct initial state",()=>{
176-
constprovider=newWorkspaceProvider(
232+
constprovider=newTestableWorkspaceProvider(
177233
WorkspaceQuery.All,
178234
mockRestClient,
179235
mockStorage,
180236
10
181237
)
182238

183239
expect(provider).toBeDefined()
240+
expect(provider.getVisible()).toBe(false)
241+
expect(provider.getWorkspaces()).toBeUndefined()
184242
})
185243

186244
it("should create provider without timer",()=>{
187-
constprovider=newWorkspaceProvider(
245+
constprovider=newTestableWorkspaceProvider(
188246
WorkspaceQuery.Mine,
189247
mockRestClient,
190248
mockStorage
@@ -194,6 +252,15 @@ describe("WorkspaceProvider", () => {
194252
})
195253
})
196254

255+
describe("createEventEmitter",()=>{
256+
it("should create and return event emitter",()=>{
257+
constemitter=provider.createEventEmitter()
258+
259+
expect(vscode.EventEmitter).toHaveBeenCalled()
260+
expect(emitter).toBe(mockEventEmitter)
261+
})
262+
})
263+
197264
describe("fetchAndRefresh",()=>{
198265
it("should not fetch when not visible",async()=>{
199266
provider.setVisibility(false)
@@ -203,13 +270,30 @@ describe("WorkspaceProvider", () => {
203270
expect(mockRestClient.getWorkspaces).not.toHaveBeenCalled()
204271
})
205272

273+
it("should not fetch when already fetching",async()=>{
274+
// Mock the handleVisibilityChange to prevent automatic fetchAndRefresh
275+
consthandleVisibilitySpy=vi.spyOn(provider,"handleVisibilityChange").mockImplementation(()=>{})
276+
provider.setVisibility(true)
277+
handleVisibilitySpy.mockRestore()
278+
279+
provider.setFetching(true)
280+
281+
awaitprovider.fetchAndRefresh()
282+
283+
expect(mockRestClient.getWorkspaces).not.toHaveBeenCalled()
284+
})
285+
206286
it("should fetch workspaces successfully",async()=>{
207287
mockRestClient.getWorkspaces.mockResolvedValue({
208288
workspaces:[mockWorkspace],
209289
count:1,
210290
})
211291

292+
// Mock the handleVisibilityChange to prevent automatic fetchAndRefresh
293+
consthandleVisibilitySpy=vi.spyOn(provider,"handleVisibilityChange").mockImplementation(()=>{})
212294
provider.setVisibility(true)
295+
handleVisibilitySpy.mockRestore()
296+
213297
awaitprovider.fetchAndRefresh()
214298

215299
expect(mockRestClient.getWorkspaces).toHaveBeenCalledWith({
@@ -221,7 +305,11 @@ describe("WorkspaceProvider", () => {
221305
it("should handle fetch errors gracefully",async()=>{
222306
mockRestClient.getWorkspaces.mockRejectedValue(newError("Network error"))
223307

308+
// Mock the handleVisibilityChange to prevent automatic fetchAndRefresh
309+
consthandleVisibilitySpy=vi.spyOn(provider,"handleVisibilityChange").mockImplementation(()=>{})
224310
provider.setVisibility(true)
311+
handleVisibilitySpy.mockRestore()
312+
225313
awaitprovider.fetchAndRefresh()
226314

227315
expect(mockEventEmitter.fire).toHaveBeenCalled()
@@ -240,7 +328,11 @@ describe("WorkspaceProvider", () => {
240328
count:0,
241329
})
242330

331+
// Mock the handleVisibilityChange to prevent automatic fetchAndRefresh
332+
consthandleVisibilitySpy=vi.spyOn(provider,"handleVisibilityChange").mockImplementation(()=>{})
243333
provider.setVisibility(true)
334+
handleVisibilitySpy.mockRestore()
335+
244336
awaitprovider.fetchAndRefresh()
245337

246338
expect(mockStorage.writeToCoderOutputChannel).toHaveBeenCalledWith(
@@ -252,19 +344,43 @@ describe("WorkspaceProvider", () => {
252344
})
253345

254346
describe("setVisibility",()=>{
347+
it("should set visibility and call handleVisibilityChange",()=>{
348+
consthandleVisibilitySpy=vi.spyOn(provider,"handleVisibilityChange").mockImplementation(()=>{})
349+
350+
provider.setVisibility(true)
351+
352+
expect(provider.getVisible()).toBe(true)
353+
expect(handleVisibilitySpy).toHaveBeenCalledWith(true)
354+
})
355+
})
356+
357+
describe("handleVisibilityChange",()=>{
255358
it("should start fetching when becoming visible for first time",async()=>{
256359
constfetchSpy=vi.spyOn(provider,"fetchAndRefresh").mockResolvedValue()
257360

258-
provider.setVisibility(true)
361+
provider.handleVisibilityChange(true)
259362

260363
expect(fetchSpy).toHaveBeenCalled()
261364
})
262365

366+
it("should not fetch when workspaces already exist",()=>{
367+
constfetchSpy=vi.spyOn(provider,"fetchAndRefresh").mockResolvedValue()
368+
369+
// Set workspaces to simulate having fetched before
370+
provider.setWorkspaces([])
371+
372+
provider.handleVisibilityChange(true)
373+
374+
expect(fetchSpy).not.toHaveBeenCalled()
375+
})
376+
263377
it("should cancel pending refresh when becoming invisible",()=>{
264378
vi.useFakeTimers()
265379

266-
provider.setVisibility(true)
267-
provider.setVisibility(false)
380+
// First set visible to potentially schedule refresh
381+
provider.handleVisibilityChange(true)
382+
// Then set invisible to cancel
383+
provider.handleVisibilityChange(false)
268384

269385
// Fast-forward time - should not trigger refresh
270386
vi.advanceTimersByTime(10000)
@@ -299,7 +415,11 @@ describe("WorkspaceProvider", () => {
299415
count:1,
300416
})
301417

418+
// Mock the handleVisibilityChange to prevent automatic fetchAndRefresh
419+
consthandleVisibilitySpy=vi.spyOn(provider,"handleVisibilityChange").mockImplementation(()=>{})
302420
provider.setVisibility(true)
421+
handleVisibilitySpy.mockRestore()
422+
303423
awaitprovider.fetchAndRefresh()
304424

305425
constchildren=awaitprovider.getChildren()
@@ -333,13 +453,50 @@ describe("WorkspaceProvider", () => {
333453
})
334454
})
335455

336-
describe("fetch method edge cases",()=>{
456+
describe("createWorkspaceTreeItem",()=>{
457+
it("should create workspace tree item with app status",async()=>{
458+
const{ extractAgents}=awaitimport("./api-helper")
459+
460+
constagentWithApps={
461+
...mockAgent,
462+
apps:[
463+
{
464+
display_name:"Test App",
465+
url:"https://app.example.com",
466+
command:"npm start",
467+
},
468+
],
469+
}
470+
471+
vi.mocked(extractAgents).mockReturnValue([agentWithApps])
472+
473+
constresult=provider.createWorkspaceTreeItem(mockWorkspace)
474+
475+
expect(result).toBeInstanceOf(WorkspaceTreeItem)
476+
expect(result.appStatus).toEqual([
477+
{
478+
name:"Test App",
479+
url:"https://app.example.com",
480+
agent_id:"agent-1",
481+
agent_name:"main",
482+
command:"npm start",
483+
workspace_name:"test-workspace",
484+
},
485+
])
486+
})
487+
})
488+
489+
describe("edge cases",()=>{
337490
it("should throw error when not logged in",async()=>{
338491
mockRestClient.getAxiosInstance.mockReturnValue({
339492
defaults:{baseURL:undefined},
340493
})
341494

495+
// Mock the handleVisibilityChange to prevent automatic fetchAndRefresh
496+
consthandleVisibilitySpy=vi.spyOn(provider,"handleVisibilityChange").mockImplementation(()=>{})
342497
provider.setVisibility(true)
498+
handleVisibilitySpy.mockRestore()
499+
343500
awaitprovider.fetchAndRefresh()
344501

345502
// Should result in empty workspaces due to error handling
@@ -348,7 +505,7 @@ describe("WorkspaceProvider", () => {
348505
})
349506

350507
it("should handle workspace query for All workspaces",async()=>{
351-
constallProvider=newWorkspaceProvider(
508+
constallProvider=newTestableWorkspaceProvider(
352509
WorkspaceQuery.All,
353510
mockRestClient,
354511
mockStorage,
@@ -360,7 +517,11 @@ describe("WorkspaceProvider", () => {
360517
count:1,
361518
})
362519

520+
// Mock the handleVisibilityChange to prevent automatic fetchAndRefresh
521+
consthandleVisibilitySpy=vi.spyOn(allProvider,"handleVisibilityChange").mockImplementation(()=>{})
363522
allProvider.setVisibility(true)
523+
handleVisibilitySpy.mockRestore()
524+
364525
awaitallProvider.fetchAndRefresh()
365526

366527
expect(mockRestClient.getWorkspaces).toHaveBeenCalledWith({

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp