@@ -8,6 +8,22 @@ import { createDefinition, deleteDefinitionByFieldKey } from '../support/profile
88const adminUser = process . env . NEXTCLOUD_ADMIN_USER ?? 'admin'
99const adminPassword = process . env . NEXTCLOUD_ADMIN_PASSWORD ?? 'admin'
1010
11+ const optionInput = ( page , index : number ) => page . getByTestId ( `profile-fields-admin-option-row-${ index } ` ) . locator ( 'input' )
12+
13+ const chooseFieldType = async ( page , label : 'Text' | 'Number' | 'Select' ) => {
14+ await page . getByTestId ( 'profile-fields-admin-type-select' ) . click ( )
15+ await page . getByRole ( 'option' , { name : label , exact : true } ) . click ( )
16+ }
17+
18+ const openSelectDefinitionEditor = async ( page , fieldKey : string , label : string ) => {
19+ await page . goto ( './settings/admin/profile_fields' )
20+ await expect ( page . getByTestId ( 'profile-fields-admin' ) ) . toBeVisible ( )
21+
22+ await page . getByTestId ( `profile-fields-admin-definition-${ fieldKey } ` ) . click ( )
23+ await expect ( page . locator ( '#profile-fields-admin-label' ) ) . toHaveValue ( label )
24+ await expect ( page . getByTestId ( 'profile-fields-admin-option-row-0' ) ) . toBeVisible ( )
25+ }
26+
1127const collectEmbeddedLayoutMetrics = async ( page , fieldKey : string ) => {
1228 const aboutInput = page . getByRole ( 'textbox' , { name : 'About' } )
1329 const customField = page . getByTestId ( `profile-fields-personal-field-${ fieldKey } ` )
@@ -95,6 +111,207 @@ test('admin can create, update, and delete a field definition', async ({ page })
95111 await deleteDefinitionByFieldKey ( page . request , fieldKey )
96112} )
97113
114+ test ( 'admin gets an initial select option row and can remove empty rows by keyboard' , async ( { page } ) => {
115+ const suffix = Date . now ( )
116+ const fieldKey = `playwright_select_create_${ suffix } `
117+ const label = `Playwright select create ${ suffix } `
118+
119+ await deleteDefinitionByFieldKey ( page . request , fieldKey )
120+
121+ await page . goto ( './settings/admin/profile_fields' )
122+ await expect ( page . getByTestId ( 'profile-fields-admin' ) ) . toBeVisible ( )
123+
124+ await page . getByTestId ( 'profile-fields-admin-new-field' ) . click ( )
125+ await page . locator ( '#profile-fields-admin-field-key' ) . fill ( fieldKey )
126+ await page . locator ( '#profile-fields-admin-label' ) . fill ( label )
127+ await chooseFieldType ( page , 'Select' )
128+
129+ await expect ( page . getByTestId ( 'profile-fields-admin-option-row-0' ) ) . toBeVisible ( )
130+ await expect ( optionInput ( page , 0 ) ) . toBeFocused ( )
131+ await expect ( optionInput ( page , 0 ) ) . toHaveValue ( '' )
132+ await expect ( page . locator ( '[data-testid^="profile-fields-admin-option-handle-"]' ) ) . toHaveCount ( 0 )
133+
134+ await optionInput ( page , 0 ) . fill ( 'Alpha' )
135+ await optionInput ( page , 0 ) . press ( 'Enter' )
136+ await expect ( page . getByTestId ( 'profile-fields-admin-option-row-1' ) ) . toBeVisible ( )
137+ await expect ( optionInput ( page , 1 ) ) . toBeFocused ( )
138+
139+ await page . locator ( '#profile-fields-admin-label' ) . click ( )
140+ await expect ( page . getByTestId ( 'profile-fields-admin-option-row-1' ) ) . toHaveCount ( 0 )
141+
142+ await optionInput ( page , 0 ) . press ( 'Enter' )
143+ await expect ( page . getByTestId ( 'profile-fields-admin-option-row-1' ) ) . toBeVisible ( )
144+ await expect ( optionInput ( page , 1 ) ) . toBeFocused ( )
145+
146+ await optionInput ( page , 1 ) . press ( 'Backspace' )
147+ await expect ( page . getByTestId ( 'profile-fields-admin-option-row-1' ) ) . toHaveCount ( 0 )
148+ await expect ( optionInput ( page , 0 ) ) . toBeFocused ( )
149+ await expect ( page . getByTestId ( 'profile-fields-admin-option-handle-0' ) ) . toBeVisible ( )
150+
151+ await page . getByTestId ( 'profile-fields-admin-save' ) . click ( )
152+ await expect ( page . getByTestId ( 'profile-fields-admin-success' ) ) . toContainText ( 'Field definition created.' )
153+
154+ await deleteDefinitionByFieldKey ( page . request , fieldKey )
155+ } )
156+
157+ test ( 'admin can bulk add select options from multiple lines' , async ( { page } ) => {
158+ const suffix = Date . now ( )
159+ const fieldKey = `playwright_select_bulk_${ suffix } `
160+ const label = `Playwright select bulk ${ suffix } `
161+
162+ await deleteDefinitionByFieldKey ( page . request , fieldKey )
163+
164+ await page . goto ( './settings/admin/profile_fields' )
165+ await expect ( page . getByTestId ( 'profile-fields-admin' ) ) . toBeVisible ( )
166+
167+ await page . getByTestId ( 'profile-fields-admin-new-field' ) . click ( )
168+ await page . locator ( '#profile-fields-admin-field-key' ) . fill ( fieldKey )
169+ await page . locator ( '#profile-fields-admin-label' ) . fill ( label )
170+ await chooseFieldType ( page , 'Select' )
171+
172+ await page . getByTestId ( 'profile-fields-admin-add-multiple-options' ) . click ( )
173+ await page . getByTestId ( 'profile-fields-admin-bulk-options-input' ) . fill ( 'Alpha\n\n Beta \nGamma' )
174+ await page . getByTestId ( 'profile-fields-admin-bulk-options-submit' ) . click ( )
175+
176+ await expect ( optionInput ( page , 0 ) ) . toHaveValue ( 'Alpha' )
177+ await expect ( optionInput ( page , 1 ) ) . toHaveValue ( 'Beta' )
178+ await expect ( optionInput ( page , 2 ) ) . toHaveValue ( 'Gamma' )
179+ await expect ( page . locator ( '[data-testid^="profile-fields-admin-option-handle-"]' ) ) . toHaveCount ( 3 )
180+
181+ const continuationRow = page . getByTestId ( 'profile-fields-admin-option-row-3' )
182+ if ( await continuationRow . count ( ) ) {
183+ await expect ( continuationRow . locator ( 'input' ) ) . toHaveValue ( '' )
184+ }
185+
186+ await page . getByTestId ( 'profile-fields-admin-save' ) . click ( )
187+ await expect ( page . getByTestId ( 'profile-fields-admin-success' ) ) . toContainText ( 'Field definition created.' )
188+
189+ await deleteDefinitionByFieldKey ( page . request , fieldKey )
190+ } )
191+
192+ test ( 'admin reuses the empty select option row on repeated Enter' , async ( { page } ) => {
193+ const suffix = Date . now ( )
194+ const fieldKey = `playwright_select_${ suffix } `
195+ const label = `Playwright select ${ suffix } `
196+
197+ await deleteDefinitionByFieldKey ( page . request , fieldKey )
198+ await createDefinition ( page . request , {
199+ fieldKey,
200+ label,
201+ type : 'select' ,
202+ options : [ 'Alpha' , 'Beta' , 'Gamma' ] ,
203+ } )
204+
205+ try {
206+ await openSelectDefinitionEditor ( page , fieldKey , label )
207+ await expect ( optionInput ( page , 0 ) ) . toHaveValue ( 'Alpha' )
208+ await expect ( optionInput ( page , 1 ) ) . toHaveValue ( 'Beta' )
209+ await expect ( optionInput ( page , 2 ) ) . toHaveValue ( 'Gamma' )
210+
211+ await optionInput ( page , 2 ) . press ( 'Enter' )
212+ await expect ( page . getByTestId ( 'profile-fields-admin-option-row-3' ) ) . toBeVisible ( )
213+ await expect ( optionInput ( page , 3 ) ) . toHaveValue ( '' )
214+ await expect ( optionInput ( page , 3 ) ) . toBeFocused ( )
215+ await expect ( page . locator ( '[data-testid^="profile-fields-admin-option-handle-"]' ) ) . toHaveCount ( 3 )
216+
217+ await optionInput ( page , 3 ) . fill ( 'Delta' )
218+ await expect ( page . getByTestId ( 'profile-fields-admin-option-handle-3' ) ) . toBeVisible ( )
219+ await expect ( page . locator ( '[data-testid^="profile-fields-admin-option-handle-"]' ) ) . toHaveCount ( 4 )
220+
221+ await optionInput ( page , 3 ) . press ( 'Enter' )
222+ await expect ( page . getByTestId ( 'profile-fields-admin-option-row-4' ) ) . toBeVisible ( )
223+ await expect ( optionInput ( page , 4 ) ) . toHaveValue ( '' )
224+ await expect ( optionInput ( page , 4 ) ) . toBeFocused ( )
225+ await expect ( page . getByTestId ( 'profile-fields-admin-option-handle-3' ) ) . toBeVisible ( )
226+ await expect ( page . locator ( '[data-testid^="profile-fields-admin-option-handle-"]' ) ) . toHaveCount ( 4 )
227+
228+ await optionInput ( page , 4 ) . press ( 'Enter' )
229+ await expect ( page . getByTestId ( 'profile-fields-admin-option-row-4' ) ) . toBeVisible ( )
230+ await expect ( page . getByTestId ( 'profile-fields-admin-option-row-5' ) ) . toHaveCount ( 0 )
231+ await expect ( optionInput ( page , 4 ) ) . toBeFocused ( )
232+ await expect ( page . locator ( '[data-testid^="profile-fields-admin-option-handle-"]' ) ) . toHaveCount ( 4 )
233+
234+ await page . getByTestId ( 'profile-fields-admin-option-handle-3' ) . click ( )
235+ await page . getByRole ( 'menuitem' , { name : 'Move up' } ) . click ( )
236+
237+ await expect ( optionInput ( page , 0 ) ) . toHaveValue ( 'Alpha' )
238+ await expect ( optionInput ( page , 1 ) ) . toHaveValue ( 'Beta' )
239+ await expect ( optionInput ( page , 2 ) ) . toHaveValue ( 'Delta' )
240+ await expect ( optionInput ( page , 3 ) ) . toHaveValue ( 'Gamma' )
241+
242+ await page . getByTestId ( 'profile-fields-admin-option-handle-2' ) . dragTo ( page . getByTestId ( 'profile-fields-admin-option-handle-1' ) )
243+
244+ await expect ( optionInput ( page , 0 ) ) . toHaveValue ( 'Alpha' )
245+ await expect ( optionInput ( page , 1 ) ) . toHaveValue ( 'Delta' )
246+ await expect ( optionInput ( page , 2 ) ) . toHaveValue ( 'Beta' )
247+ await expect ( optionInput ( page , 3 ) ) . toHaveValue ( 'Gamma' )
248+ await expect ( page . getByTestId ( 'profile-fields-admin-option-row-4' ) ) . toHaveCount ( 0 )
249+
250+ await page . getByTestId ( 'profile-fields-admin-save' ) . click ( )
251+ await expect ( page . getByTestId ( 'profile-fields-admin-success' ) ) . toContainText ( 'Field definition updated.' )
252+
253+ await page . reload ( )
254+ await openSelectDefinitionEditor ( page , fieldKey , label )
255+ await expect ( optionInput ( page , 0 ) ) . toHaveValue ( 'Alpha' )
256+ await expect ( optionInput ( page , 1 ) ) . toHaveValue ( 'Delta' )
257+ await expect ( optionInput ( page , 2 ) ) . toHaveValue ( 'Beta' )
258+ await expect ( optionInput ( page , 3 ) ) . toHaveValue ( 'Gamma' )
259+ await expect ( page . getByTestId ( 'profile-fields-admin-option-row-4' ) ) . toHaveCount ( 0 )
260+ } finally {
261+ await deleteDefinitionByFieldKey ( page . request , fieldKey )
262+ }
263+ } )
264+
265+ test ( 'admin can reorder select options from the handle menu and drag handle' , async ( { page } ) => {
266+ const suffix = Date . now ( )
267+ const fieldKey = `playwright_reorder_${ suffix } `
268+ const label = `Playwright reorder ${ suffix } `
269+
270+ await deleteDefinitionByFieldKey ( page . request , fieldKey )
271+ await createDefinition ( page . request , {
272+ fieldKey,
273+ label,
274+ type : 'select' ,
275+ options : [ 'Alpha' , 'Beta' , 'Gamma' , 'Delta' ] ,
276+ } )
277+
278+ try {
279+ await openSelectDefinitionEditor ( page , fieldKey , label )
280+ await expect ( optionInput ( page , 0 ) ) . toHaveValue ( 'Alpha' )
281+ await expect ( optionInput ( page , 1 ) ) . toHaveValue ( 'Beta' )
282+ await expect ( optionInput ( page , 2 ) ) . toHaveValue ( 'Gamma' )
283+ await expect ( optionInput ( page , 3 ) ) . toHaveValue ( 'Delta' )
284+ await expect ( page . locator ( '[data-testid^="profile-fields-admin-option-handle-"]' ) ) . toHaveCount ( 4 )
285+
286+ await page . getByTestId ( 'profile-fields-admin-option-handle-3' ) . click ( )
287+ await page . getByRole ( 'menuitem' , { name : 'Move up' } ) . click ( )
288+
289+ await expect ( optionInput ( page , 0 ) ) . toHaveValue ( 'Alpha' )
290+ await expect ( optionInput ( page , 1 ) ) . toHaveValue ( 'Beta' )
291+ await expect ( optionInput ( page , 2 ) ) . toHaveValue ( 'Delta' )
292+ await expect ( optionInput ( page , 3 ) ) . toHaveValue ( 'Gamma' )
293+
294+ await page . getByTestId ( 'profile-fields-admin-option-handle-2' ) . dragTo ( page . getByTestId ( 'profile-fields-admin-option-handle-1' ) )
295+
296+ await expect ( optionInput ( page , 0 ) ) . toHaveValue ( 'Alpha' )
297+ await expect ( optionInput ( page , 1 ) ) . toHaveValue ( 'Delta' )
298+ await expect ( optionInput ( page , 2 ) ) . toHaveValue ( 'Beta' )
299+ await expect ( optionInput ( page , 3 ) ) . toHaveValue ( 'Gamma' )
300+
301+ await page . getByTestId ( 'profile-fields-admin-save' ) . click ( )
302+ await expect ( page . getByTestId ( 'profile-fields-admin-success' ) ) . toContainText ( 'Field definition updated.' )
303+
304+ await page . reload ( )
305+ await openSelectDefinitionEditor ( page , fieldKey , label )
306+ await expect ( optionInput ( page , 0 ) ) . toHaveValue ( 'Alpha' )
307+ await expect ( optionInput ( page , 1 ) ) . toHaveValue ( 'Delta' )
308+ await expect ( optionInput ( page , 2 ) ) . toHaveValue ( 'Beta' )
309+ await expect ( optionInput ( page , 3 ) ) . toHaveValue ( 'Gamma' )
310+ } finally {
311+ await deleteDefinitionByFieldKey ( page . request , fieldKey )
312+ }
313+ } )
314+
98315test ( 'embedded personal settings autosave a user-visible field' , async ( { page } ) => {
99316 const suffix = Date . now ( )
100317 const fieldKey = `playwright_personal_${ suffix } `
0 commit comments