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

Commit9a5f639

Browse files
committed
add tests
1 parent2036479 commit9a5f639

File tree

2 files changed

+279
-1
lines changed

2 files changed

+279
-1
lines changed

‎cli/exp_tasklist_test.go‎

Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
package cli_test
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"database/sql"
7+
"encoding/json"
8+
"io"
9+
"testing"
10+
11+
"github.com/google/uuid"
12+
"github.com/stretchr/testify/require"
13+
14+
"cdr.dev/slog"
15+
"cdr.dev/slog/sloggers/sloghuman"
16+
17+
"github.com/coder/coder/v2/cli/clitest"
18+
"github.com/coder/coder/v2/coderd/coderdtest"
19+
"github.com/coder/coder/v2/coderd/database"
20+
"github.com/coder/coder/v2/coderd/database/dbauthz"
21+
"github.com/coder/coder/v2/coderd/database/dbfake"
22+
"github.com/coder/coder/v2/coderd/database/dbgen"
23+
"github.com/coder/coder/v2/coderd/util/slice"
24+
"github.com/coder/coder/v2/codersdk"
25+
"github.com/coder/coder/v2/pty/ptytest"
26+
"github.com/coder/coder/v2/testutil"
27+
)
28+
29+
// makeAITask creates an AI-task workspace.
30+
funcmakeAITask(t*testing.T,db database.Store,orgID,adminID,ownerID uuid.UUID,transition database.WorkspaceTransition,promptstring) (workspace database.WorkspaceTable) {
31+
t.Helper()
32+
33+
tv:=dbfake.TemplateVersion(t,db).
34+
Seed(database.TemplateVersion{
35+
OrganizationID:orgID,
36+
CreatedBy:adminID,
37+
HasAITask: sql.NullBool{
38+
Bool:true,
39+
Valid:true,
40+
},
41+
}).Do()
42+
43+
ws:= database.WorkspaceTable{
44+
OrganizationID:orgID,
45+
OwnerID:ownerID,
46+
TemplateID:tv.Template.ID,
47+
}
48+
build:=dbfake.WorkspaceBuild(t,db,ws).
49+
Seed(database.WorkspaceBuild{
50+
TemplateVersionID:tv.TemplateVersion.ID,
51+
Transition:transition,
52+
}).WithAgent().Do()
53+
dbgen.WorkspaceBuildParameters(t,db, []database.WorkspaceBuildParameter{
54+
{
55+
WorkspaceBuildID:build.Build.ID,
56+
Name:codersdk.AITaskPromptParameterName,
57+
Value:prompt,
58+
},
59+
})
60+
agents,err:=db.GetWorkspaceAgentsByWorkspaceAndBuildNumber(
61+
dbauthz.AsSystemRestricted(context.Background()),
62+
database.GetWorkspaceAgentsByWorkspaceAndBuildNumberParams{
63+
WorkspaceID:build.Workspace.ID,
64+
BuildNumber:build.Build.BuildNumber,
65+
},
66+
)
67+
require.NoError(t,err)
68+
require.NotEmpty(t,agents)
69+
agentID:=agents[0].ID
70+
71+
// Create a workspace app and set it as the sidebar app.
72+
app:=dbgen.WorkspaceApp(t,db, database.WorkspaceApp{
73+
AgentID:agentID,
74+
Slug:"task-sidebar",
75+
DisplayName:"Task Sidebar",
76+
External:false,
77+
})
78+
79+
// Update build flags to reference the sidebar app and HasAITask=true.
80+
err=db.UpdateWorkspaceBuildFlagsByID(
81+
dbauthz.AsSystemRestricted(context.Background()),
82+
database.UpdateWorkspaceBuildFlagsByIDParams{
83+
ID:build.Build.ID,
84+
HasAITask: sql.NullBool{Bool:true,Valid:true},
85+
HasExternalAgent: sql.NullBool{Bool:false,Valid:false},
86+
SidebarAppID: uuid.NullUUID{UUID:app.ID,Valid:true},
87+
UpdatedAt:build.Build.UpdatedAt,
88+
},
89+
)
90+
require.NoError(t,err)
91+
92+
returnbuild.Workspace
93+
}
94+
95+
funcTestExpTaskList(t*testing.T) {
96+
t.Parallel()
97+
98+
t.Run("NoTasks_Table",func(t*testing.T) {
99+
t.Parallel()
100+
101+
// Quiet logger to reduce noise.
102+
quiet:=slog.Make(sloghuman.Sink(io.Discard))
103+
client,_:=coderdtest.NewWithDatabase(t,&coderdtest.Options{Logger:&quiet})
104+
owner:=coderdtest.CreateFirstUser(t,client)
105+
memberClient,_:=coderdtest.CreateAnotherUser(t,client,owner.OrganizationID)
106+
107+
inv,root:=clitest.New(t,"exp","task","list")
108+
clitest.SetupConfig(t,memberClient,root)
109+
110+
pty:=ptytest.New(t).Attach(inv)
111+
ctx:=testutil.Context(t,testutil.WaitShort)
112+
113+
err:=inv.WithContext(ctx).Run()
114+
require.NoError(t,err)
115+
116+
pty.ExpectMatch("No tasks found.")
117+
})
118+
119+
t.Run("Single_Table",func(t*testing.T) {
120+
t.Parallel()
121+
122+
// Quiet logger to reduce noise.
123+
quiet:=slog.Make(sloghuman.Sink(io.Discard))
124+
client,db:=coderdtest.NewWithDatabase(t,&coderdtest.Options{Logger:&quiet})
125+
owner:=coderdtest.CreateFirstUser(t,client)
126+
memberClient,memberUser:=coderdtest.CreateAnotherUser(t,client,owner.OrganizationID)
127+
128+
wantPrompt:="build me a web app"
129+
ws:=makeAITask(t,db,owner.OrganizationID,owner.UserID,memberUser.ID,database.WorkspaceTransitionStart,wantPrompt)
130+
131+
inv,root:=clitest.New(t,"exp","task","list","--column","id,name,status,initial prompt")
132+
clitest.SetupConfig(t,memberClient,root)
133+
134+
pty:=ptytest.New(t).Attach(inv)
135+
ctx:=testutil.Context(t,testutil.WaitShort)
136+
137+
err:=inv.WithContext(ctx).Run()
138+
require.NoError(t,err)
139+
140+
// Validate the table includes the task and status.
141+
pty.ExpectMatch(ws.Name)
142+
pty.ExpectMatch("running")
143+
pty.ExpectMatch(wantPrompt)
144+
})
145+
146+
t.Run("StatusFilter_JSON",func(t*testing.T) {
147+
t.Parallel()
148+
149+
// Quiet logger to reduce noise.
150+
quiet:=slog.Make(sloghuman.Sink(io.Discard))
151+
client,db:=coderdtest.NewWithDatabase(t,&coderdtest.Options{Logger:&quiet})
152+
owner:=coderdtest.CreateFirstUser(t,client)
153+
memberClient,memberUser:=coderdtest.CreateAnotherUser(t,client,owner.OrganizationID)
154+
155+
// Create two AI tasks: one running, one stopped.
156+
running:=makeAITask(t,db,owner.OrganizationID,owner.UserID,memberUser.ID,database.WorkspaceTransitionStart,"keep me running")
157+
stopped:=makeAITask(t,db,owner.OrganizationID,owner.UserID,memberUser.ID,database.WorkspaceTransitionStop,"stop me please")
158+
159+
// Use JSON output to reliably validate filtering.
160+
inv,root:=clitest.New(t,"exp","task","list","--status=stopped","--output=json")
161+
clitest.SetupConfig(t,memberClient,root)
162+
163+
ctx:=testutil.Context(t,testutil.WaitShort)
164+
varstdout bytes.Buffer
165+
inv.Stdout=&stdout
166+
inv.Stderr=&stdout
167+
168+
err:=inv.WithContext(ctx).Run()
169+
require.NoError(t,err)
170+
171+
vartasks []codersdk.Task
172+
require.NoError(t,json.Unmarshal(stdout.Bytes(),&tasks))
173+
174+
// Only the stopped task is returned.
175+
require.Len(t,tasks,1,"expected one task after filtering")
176+
require.Equal(t,stopped.ID,tasks[0].ID)
177+
require.NotEqual(t,running.ID,tasks[0].ID)
178+
})
179+
180+
t.Run("UserFlag_Me_Table",func(t*testing.T) {
181+
t.Parallel()
182+
183+
quiet:=slog.Make(sloghuman.Sink(io.Discard))
184+
client,db:=coderdtest.NewWithDatabase(t,&coderdtest.Options{Logger:&quiet})
185+
owner:=coderdtest.CreateFirstUser(t,client)
186+
_,memberUser:=coderdtest.CreateAnotherUser(t,client,owner.OrganizationID)
187+
188+
_=makeAITask(t,db,owner.OrganizationID,owner.UserID,memberUser.ID,database.WorkspaceTransitionStart,"other-task")
189+
ws:=makeAITask(t,db,owner.OrganizationID,owner.UserID,owner.UserID,database.WorkspaceTransitionStart,"me-task")
190+
191+
inv,root:=clitest.New(t,"exp","task","list","--user","me")
192+
//nolint:gocritic // Owner client is intended here smoke test the member task not showing up.
193+
clitest.SetupConfig(t,client,root)
194+
195+
pty:=ptytest.New(t).Attach(inv)
196+
ctx:=testutil.Context(t,testutil.WaitShort)
197+
198+
err:=inv.WithContext(ctx).Run()
199+
require.NoError(t,err)
200+
201+
pty.ExpectMatch(ws.Name)
202+
})
203+
}
204+
205+
funcTestExpTaskList_OwnerCanListOthers(t*testing.T) {
206+
t.Parallel()
207+
208+
// Quiet logger to reduce noise.
209+
quiet:=slog.Make(sloghuman.Sink(io.Discard))
210+
ownerClient,db:=coderdtest.NewWithDatabase(t,&coderdtest.Options{Logger:&quiet})
211+
owner:=coderdtest.CreateFirstUser(t,ownerClient)
212+
213+
// Create two additional members in the owner's organization.
214+
_,memberAUser:=coderdtest.CreateAnotherUser(t,ownerClient,owner.OrganizationID)
215+
_,memberBUser:=coderdtest.CreateAnotherUser(t,ownerClient,owner.OrganizationID)
216+
217+
// Seed an AI task for member A and B.
218+
_=makeAITask(t,db,owner.OrganizationID,owner.UserID,memberAUser.ID,database.WorkspaceTransitionStart,"member-A-task")
219+
_=makeAITask(t,db,owner.OrganizationID,owner.UserID,memberBUser.ID,database.WorkspaceTransitionStart,"member-B-task")
220+
221+
t.Run("OwnerListsSpecificUserWithUserFlag_JSON",func(t*testing.T) {
222+
t.Parallel()
223+
224+
// As the owner, list only member A tasks.
225+
inv,root:=clitest.New(t,"exp","task","list","--user",memberAUser.Username,"--output=json")
226+
//nolint:gocritic // Owner client is intended here to allow member tasks to be listed.
227+
clitest.SetupConfig(t,ownerClient,root)
228+
229+
varstdout bytes.Buffer
230+
inv.Stdout=&stdout
231+
232+
ctx:=testutil.Context(t,testutil.WaitShort)
233+
234+
err:=inv.WithContext(ctx).Run()
235+
require.NoError(t,err)
236+
237+
vartasks []codersdk.Task
238+
require.NoError(t,json.Unmarshal(stdout.Bytes(),&tasks))
239+
240+
// At least one task to belong to member A.
241+
require.NotEmpty(t,tasks,"expected at least one task for member A")
242+
// All tasks should belong to member A.
243+
for_,task:=rangetasks {
244+
require.Equal(t,memberAUser.ID,task.OwnerID,"expected only member A tasks")
245+
}
246+
})
247+
248+
t.Run("OwnerListsAllWithAllFlag_JSON",func(t*testing.T) {
249+
t.Parallel()
250+
251+
// As the owner, list all tasks to verify both member tasks are present.
252+
// Use JSON output to reliably validate filtering.
253+
inv,root:=clitest.New(t,"exp","task","list","--all","--output=json")
254+
//nolint:gocritic // Owner client is intended here to allow all tasks to be listed.
255+
clitest.SetupConfig(t,ownerClient,root)
256+
257+
varstdout bytes.Buffer
258+
inv.Stdout=&stdout
259+
260+
ctx:=testutil.Context(t,testutil.WaitShort)
261+
262+
err:=inv.WithContext(ctx).Run()
263+
require.NoError(t,err)
264+
265+
vartasks []codersdk.Task
266+
require.NoError(t,json.Unmarshal(stdout.Bytes(),&tasks))
267+
268+
// Expect at least two tasks and ensure both owners (member A and member B) are represented.
269+
require.GreaterOrEqual(t,len(tasks),2,"expected two or more tasks in --all listing")
270+
271+
// Use slice.Find for concise existence checks.
272+
_,foundA:=slice.Find(tasks,func(t codersdk.Task)bool {returnt.OwnerID==memberAUser.ID })
273+
_,foundB:=slice.Find(tasks,func(t codersdk.Task)bool {returnt.OwnerID==memberBUser.ID })
274+
275+
require.True(t,foundA,"expected at least one task for member A in --all listing")
276+
require.True(t,foundB,"expected at least one task for member B in --all listing")
277+
})
278+
}

‎coderd/aitasks.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ func (api *API) tasksList(rw http.ResponseWriter, r *http.Request) {
280280
// Ensure that we only include AI task workspaces in the results.
281281
filter.HasAITask= sql.NullBool{Valid:true,Bool:true}
282282

283-
iffilter.OwnerUsername=="me"||filter.OwnerUsername==""{
283+
iffilter.OwnerUsername=="me" {
284284
filter.OwnerID=apiKey.UserID
285285
filter.OwnerUsername=""
286286
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp