@@ -18,12 +18,12 @@ import {
18
18
coderMain ,
19
19
coderPort ,
20
20
defaultOrganizationName ,
21
- email ,
21
+ users ,
22
22
license ,
23
- password ,
24
23
premiumTestsRequired ,
25
24
prometheusPort ,
26
25
requireTerraformTests ,
26
+ defaultPassword ,
27
27
} from "./constants" ;
28
28
import { expectUrl } from "./expectUrl" ;
29
29
import {
@@ -62,40 +62,74 @@ export function requireTerraformProvisioner() {
62
62
}
63
63
64
64
type LoginOptions = {
65
+ username : string ;
65
66
email : string ;
66
67
password : string ;
67
68
} ;
68
69
69
- export async function login ( page : Page , options ?: LoginOptions ) {
70
+ export async function login ( page : Page , options : LoginOptions = users . admin ) {
71
+ const ctx = page . context ( ) ;
72
+ // biome-ignore lint/suspicious/noExplicitAny: shenanigans to make life easier
73
+ ( ctx as any ) [ Symbol . for ( "currentUser" ) ] = undefined ;
74
+ await ctx . clearCookies ( ) ;
70
75
await page . goto ( "/login" ) ;
71
- await page . getByLabel ( "Email" ) . fill ( options ?. email || email ) ;
72
- await page . getByLabel ( "Password" ) . fill ( options ?. password || password ) ;
76
+ await page . getByLabel ( "Email" ) . fill ( options . email ) ;
77
+ await page . getByLabel ( "Password" ) . fill ( options . password ) ;
73
78
await page . getByRole ( "button" , { name : "Sign In" } ) . click ( ) ;
74
79
await expectUrl ( page ) . toHavePathName ( "/workspaces" ) ;
80
+ // biome-ignore lint/suspicious/noExplicitAny: shenanigans to make life easier
81
+ ( ctx as any ) [ Symbol . for ( "currentUser" ) ] = options ;
75
82
}
76
83
84
+ export function currentUser ( page : Page ) : LoginOptions {
85
+ const ctx = page . context ( ) ;
86
+ // biome-ignore lint/suspicious/noExplicitAny: shenanigans to make life easier
87
+ const user = ( ctx as any ) [ Symbol . for ( "currentUser" ) ] ;
88
+
89
+ if ( ! user ) {
90
+ throw new Error ( "page context does not have a user. did you call `login`?" ) ;
91
+ }
92
+
93
+ return user ;
94
+ }
95
+
96
+ type CreateWorkspaceOptions = {
97
+ richParameters ?: RichParameter [ ] ;
98
+ buildParameters ?: WorkspaceBuildParameter [ ] ;
99
+ useExternalAuth ?: boolean ;
100
+ } ;
101
+
77
102
/**
78
103
* createWorkspace creates a workspace for a template. It does not wait for it
79
104
* to be running, but it does navigate to the page.
80
105
*/
81
106
export const createWorkspace = async (
82
107
page : Page ,
83
- templateName : string ,
84
- richParameters : RichParameter [ ] = [ ] ,
85
- buildParameters : WorkspaceBuildParameter [ ] = [ ] ,
86
- useExternalAuthProvider : string | undefined = undefined ,
108
+ template : string | { organization : string ; name : string } ,
109
+ options : CreateWorkspaceOptions = { } ,
87
110
) : Promise < string > => {
88
- await page . goto ( `/templates/${ templateName } /workspace` , {
111
+ const {
112
+ richParameters = [ ] ,
113
+ buildParameters = [ ] ,
114
+ useExternalAuth,
115
+ } = options ;
116
+
117
+ const templatePath =
118
+ typeof template === "string"
119
+ ? template
120
+ : `${ template . organization } /${ template . name } ` ;
121
+
122
+ await page . goto ( `/templates/${ templatePath } /workspace` , {
89
123
waitUntil : "domcontentloaded" ,
90
124
} ) ;
91
- await expectUrl ( page ) . toHavePathName ( `/templates/${ templateName } /workspace` ) ;
125
+ await expectUrl ( page ) . toHavePathName ( `/templates/${ templatePath } /workspace` ) ;
92
126
93
127
const name = randomName ( ) ;
94
128
await page . getByLabel ( "name" ) . fill ( name ) ;
95
129
96
130
await fillParameters ( page , richParameters , buildParameters ) ;
97
131
98
- if ( useExternalAuthProvider !== undefined ) {
132
+ if ( useExternalAuth ) {
99
133
// Create a new context for the popup which will be created when clicking the button
100
134
const popupPromise = page . waitForEvent ( "popup" ) ;
101
135
@@ -115,7 +149,9 @@ export const createWorkspace = async (
115
149
116
150
await page . getByTestId ( "form-submit" ) . click ( ) ;
117
151
118
- await expectUrl ( page ) . toHavePathName ( `/@admin/${ name } ` ) ;
152
+ const user = currentUser ( page ) ;
153
+
154
+ await expectUrl ( page ) . toHavePathName ( `/@${ user . username } /${ name } ` ) ;
119
155
120
156
await page . waitForSelector ( "[data-testid='build-status'] >> text=Running" , {
121
157
state : "visible" ,
@@ -228,6 +264,12 @@ export const createTemplate = async (
228
264
const orgPicker = page . getByLabel ( "Belongs to *" ) ;
229
265
const organizationsEnabled = await orgPicker . isVisible ( ) ;
230
266
if ( organizationsEnabled ) {
267
+ if ( orgName !== defaultOrganizationName ) {
268
+ throw new Error (
269
+ `No provisioners registered for ${ orgName } , creating this template will fail` ,
270
+ ) ;
271
+ }
272
+
231
273
await orgPicker . click ( ) ;
232
274
await page . getByText ( orgName , { exact : true } ) . click ( ) ;
233
275
}
@@ -673,8 +715,9 @@ const createTemplateVersionTar = async (
673
715
) ;
674
716
} ;
675
717
676
- export const randomName = ( ) => {
677
- return randomUUID ( ) . slice ( 0 , 8 ) ;
718
+ export const randomName = ( annotation ?: string ) => {
719
+ const base = randomUUID ( ) . slice ( 0 , 8 ) ;
720
+ return annotation ? `${ annotation } -${ base } ` : base ;
678
721
} ;
679
722
680
723
/**
@@ -1016,6 +1059,7 @@ type UserValues = {
1016
1059
username : string ;
1017
1060
email : string ;
1018
1061
password : string ;
1062
+ roles : string [ ] ;
1019
1063
} ;
1020
1064
1021
1065
export async function createUser (
@@ -1033,7 +1077,8 @@ export async function createUser(
1033
1077
const username = userValues . username ?? randomName ( ) ;
1034
1078
const name = userValues . name ?? username ;
1035
1079
const email = userValues . email ?? `${ username } @coder.com` ;
1036
- const password = userValues . password || "s3cure&password!" ;
1080
+ const password = userValues . password || defaultPassword ;
1081
+ const roles = userValues . roles ?? [ ] ;
1037
1082
1038
1083
await page . getByLabel ( "Username" ) . fill ( username ) ;
1039
1084
if ( name ) {
@@ -1050,10 +1095,18 @@ export async function createUser(
1050
1095
await expect ( page . getByText ( "Successfully created user." ) ) . toBeVisible ( ) ;
1051
1096
1052
1097
await expect ( page ) . toHaveTitle ( "Users - Coder" ) ;
1053
- await expect ( page . locator ( "tr" , { hasText : email } ) ) . toBeVisible ( ) ;
1098
+ const addedRow = page . locator ( "tr" , { hasText : email } ) ;
1099
+ await expect ( addedRow ) . toBeVisible ( ) ;
1100
+
1101
+ // Give them a role
1102
+ await addedRow . getByLabel ( "Edit user roles" ) . click ( ) ;
1103
+ for ( const role of roles ) {
1104
+ await page . getByText ( role , { exact : true } ) . click ( ) ;
1105
+ }
1106
+ await page . mouse . click ( 10 , 10 ) ; // close the popover by clicking outside of it
1054
1107
1055
1108
await page . goto ( returnTo , { waitUntil : "domcontentloaded" } ) ;
1056
- return { name, username, email, password } ;
1109
+ return { name, username, email, password, roles } ;
1057
1110
}
1058
1111
1059
1112
export async function createOrganization ( page : Page ) : Promise < {
0 commit comments