@@ -12,7 +12,12 @@ import ClassificationIdentifierTypes from '../../../support/fragments/settings/i
1212import TopMenu from '../../../support/fragments/topMenu' ;
1313import Users from '../../../support/fragments/users/users' ;
1414import DateTools from '../../../support/utils/dateTools' ;
15- import { generateDatePickerCustomFieldData } from '../../../support/utils/customFields' ;
15+ import {
16+ generateDatePickerCustomFieldData ,
17+ generateMultiSelectCustomFieldData ,
18+ generateRadioButtonCustomFieldData ,
19+ generateSingleSelectCustomFieldData ,
20+ } from '../../../support/utils/customFields' ;
1621import { poll } from '../../../support/utils/polling' ;
1722import { getCurrentTimestamp , getTestEntityValue } from '../../../support/utils/stringTools' ;
1823import {
@@ -92,23 +97,34 @@ describe('Lists', () => {
9297 } ;
9398
9499 const waitForCustomFieldToBeQueryable = ( recordType , fieldLabel ) => {
100+ const fieldLabels = Array . isArray ( fieldLabel ) ? fieldLabel : [ fieldLabel ] ;
101+
95102 return Lists . getEntityTypeIdByNameViaApi ( recordType ) . then ( ( entityTypeId ) => {
96103 return poll (
97104 ( ) => Lists . getEntityTypeByIdViaApi ( entityTypeId , { failOnStatusCode : false } ) ,
98105 ( { body } ) => {
99- return body . columns ?. some (
100- ( { labelAlias, queryable } ) => labelAlias === fieldLabel && queryable ,
101- ) ;
106+ return fieldLabels . every ( ( label ) => body . columns ?. some ( ( { labelAlias, queryable } ) => labelAlias === label && queryable ) ) ;
102107 } ,
103108 {
104109 timeout : 360000 ,
105110 delay : 15000 ,
106- errorMessage : `"${ fieldLabel } " custom field did not become queryable for ${ recordType } ` ,
111+ errorMessage : `"${ fieldLabels . join ( ', ' ) } " custom field(s) did not become queryable for ${ recordType } ` ,
107112 } ,
108113 ) ;
109114 } ) ;
110115 } ;
111116
117+ const verifyUserFriendlyQueryText = ( { queryBuilderPreview, listDetails, expectedQuery } ) => {
118+ const actualQueryMessage = `Query builder preview: "${ queryBuilderPreview } "\nList details: "${ listDetails } "` ;
119+
120+ expect ( queryBuilderPreview , actualQueryMessage ) . to . equal ( expectedQuery ) ;
121+ expect ( listDetails , actualQueryMessage ) . to . include ( `Query: ${ expectedQuery } ` ) ;
122+ [ queryBuilderPreview , listDetails ] . forEach ( ( actualQueryText ) => {
123+ expect ( actualQueryText , actualQueryMessage ) . not . to . match ( / \b o p t _ \d + \b / ) ;
124+ expect ( actualQueryText , actualQueryMessage ) . not . to . include ( 'customfield_' ) ;
125+ } ) ;
126+ } ;
127+
112128 const verifyQueryBuilder = (
113129 field ,
114130 operator ,
@@ -258,6 +274,179 @@ describe('Lists', () => {
258274 ) ;
259275 } ) ;
260276
277+ describe ( 'Users custom field option labels' , ( ) => {
278+ const recordType = 'Users' ;
279+ const testNumber = 'C831957' ;
280+ const customFieldNamePostfix = getCurrentTimestamp ( ) ;
281+ const customFieldSpecs = {
282+ multiSelect : {
283+ fieldLabel : 'Corsair - multi select' ,
284+ generator : generateMultiSelectCustomFieldData ,
285+ multiSelect : true ,
286+ valueType : 'multiselect' ,
287+ options : [
288+ { id : 'opt_0' , value : 'Corsair - multi select1' , default : false } ,
289+ { id : 'opt_1' , value : 'Corsair - multi select2' , default : false } ,
290+ ] ,
291+ } ,
292+ singleSelect : {
293+ fieldLabel : 'Corsair - single select' ,
294+ generator : generateSingleSelectCustomFieldData ,
295+ multiSelect : false ,
296+ options : [
297+ { id : 'opt_0' , value : 'Corsair - single select1' , default : false } ,
298+ { id : 'opt_1' , value : 'Corsair - single select2' , default : false } ,
299+ ] ,
300+ } ,
301+ radioButton : {
302+ fieldLabel : 'Corsair - radio button' ,
303+ generator : generateRadioButtonCustomFieldData ,
304+ multiSelect : false ,
305+ options : [
306+ { id : 'opt_0' , value : 'Corsair - radio button1' , default : false } ,
307+ { id : 'opt_1' , value : 'Corsair - radio button2' , default : false } ,
308+ ] ,
309+ } ,
310+ } ;
311+ const queryCustomFieldKeys = Object . keys ( customFieldSpecs ) ;
312+ const getCustomFieldName = ( fieldLabel ) => `${ fieldLabel } ${ customFieldNamePostfix } ` ;
313+ const createCustomFieldData = ( { fieldLabel, generator, multiSelect, options } ) => generator ( {
314+ testNumber,
315+ data : {
316+ name : getCustomFieldName ( fieldLabel ) ,
317+ selectField : {
318+ multiSelect,
319+ options : { values : options } ,
320+ } ,
321+ } ,
322+ } ) ;
323+ const testData = {
324+ customFields : queryCustomFieldKeys . reduce ( ( customFields , key ) => {
325+ return {
326+ ...customFields ,
327+ [ key ] : createCustomFieldData ( customFieldSpecs [ key ] ) ,
328+ } ;
329+ } , { } ) ,
330+ } ;
331+ const getCustomFieldLabel = ( { name } ) => `User — ${ name } ` ;
332+ const getCustomFieldLabels = ( ) => Object . values ( testData . customFields ) . map ( getCustomFieldLabel ) ;
333+ const getCustomFieldValue = ( key ) => customFieldSpecs [ key ] . options [ 0 ] . value ;
334+ const getQueryRow = ( key , operator ) => ( {
335+ field : getCustomFieldLabel ( testData . customFields [ key ] ) ,
336+ operator,
337+ value : getCustomFieldValue ( key ) ,
338+ valueType : [ QUERY_OPERATIONS . IN , QUERY_OPERATIONS . NOT_IN ] . includes ( operator )
339+ ? customFieldSpecs [ key ] . valueType
340+ : 'select' ,
341+ } ) ;
342+
343+ const configureSelectQueryRow = ( row , { field, operator, value, valueType = 'select' } ) => {
344+ QueryModal . selectField ( field , row ) ;
345+ QueryModal . selectOperator ( operator , row ) ;
346+
347+ if ( valueType === 'multiselect' ) {
348+ QueryModal . chooseFromValueMultiselect ( value , row , { exactMatch : true } ) ;
349+ } else {
350+ QueryModal . chooseValueSelect ( value , row ) ;
351+ }
352+ } ;
353+
354+ const createQueryRows = ( queryRows ) => {
355+ queryRows . forEach ( ( queryRow , rowIndex ) => {
356+ configureSelectQueryRow ( rowIndex , queryRow ) ;
357+ if ( rowIndex < queryRows . length - 1 ) {
358+ QueryModal . addNewRow ( rowIndex ) ;
359+ }
360+ } ) ;
361+ } ;
362+
363+ before ( 'Create custom fields' , ( ) => {
364+ cy . getAdminToken ( )
365+ . then ( ( ) => cy . createCustomFieldsViaApi ( Object . values ( testData . customFields ) ) )
366+ . then ( ( createdCustomFields ) => {
367+ queryCustomFieldKeys . forEach ( ( key , index ) => {
368+ testData . customFields [ key ] = createdCustomFields [ index ] ;
369+ } ) ;
370+
371+ testData . createdCustomFieldIds = createdCustomFields . map ( ( { id } ) => id ) ;
372+
373+ return waitForCustomFieldToBeQueryable ( recordType , getCustomFieldLabels ( ) ) ;
374+ } ) ;
375+ } ) ;
376+
377+ after ( 'Delete custom field test data' , ( ) => {
378+ cy . getAdminToken ( ) ;
379+ if ( testData . createdCustomFieldIds ?. length ) {
380+ cy . deleteCustomFieldsViaApi ( {
381+ ids : testData . createdCustomFieldIds ,
382+ } ) ;
383+ }
384+ } ) ;
385+
386+ afterEach ( 'Delete test list' , ( ) => {
387+ deleteTestList ( cy . getAdminToken ) ;
388+ } ) ;
389+
390+ it (
391+ 'C831957 Verify custom field option labels in the user-friendly query (corsair)' ,
392+ { tags : [ 'extendedPath' , 'corsair' , 'C831957' ] } ,
393+ ( ) => {
394+ const multiSelectInRow = getQueryRow ( 'multiSelect' , QUERY_OPERATIONS . IN ) ;
395+ const equalsQueryRows = queryCustomFieldKeys . map ( ( key ) => getQueryRow ( key , QUERY_OPERATIONS . EQUAL ) ) ;
396+ const [ multiSelectEqualsRow , singleSelectEqualsRow , radioButtonEqualsRow ] =
397+ equalsQueryRows ;
398+ const expectedInQuery = `(${ multiSelectInRow . field } in [${ multiSelectInRow . value } ])` ;
399+ const expectedEqualsQuery =
400+ `(${ multiSelectEqualsRow . field } == ${ multiSelectEqualsRow . value } ) AND ` +
401+ `(${ singleSelectEqualsRow . field } == ${ singleSelectEqualsRow . value } ) AND ` +
402+ `(${ radioButtonEqualsRow . field } == ${ radioButtonEqualsRow . value } )` ;
403+ const actualQueries = { } ;
404+
405+ listName = getTestEntityValue ( `${ testNumber } _List` ) ;
406+ cy . loginAsAdmin ( {
407+ path : TopMenu . listsPath ,
408+ waiter : Lists . filtersWaitLoading ,
409+ } ) ;
410+
411+ Lists . openNewListPane ( ) ;
412+ Lists . setName ( listName ) ;
413+ Lists . selectRecordType ( recordType ) ;
414+ Lists . verifySelectedOptionsInRecordTypeDropdown ( recordType ) ;
415+ Lists . verifySaveButtonIsActive ( ) ;
416+ Lists . verifyCancelButtonIsActive ( ) ;
417+
418+ Lists . buildQuery ( ) ;
419+ QueryModal . verify ( ) ;
420+ QueryModal . verifyQueryTextboxReadOnly ( ) ;
421+ QueryModal . verifyQueryTextboxResizable ( ) ;
422+
423+ configureSelectQueryRow ( 0 , multiSelectInRow ) ;
424+ QueryModal . verifyQueryAreaContent ( expectedInQuery ) ;
425+ QueryModal . verifyQueryAreaDoesNotContain ( 'opt_' ) ;
426+ QueryModal . verifyQueryAreaDoesNotContain ( 'customfield_' ) ;
427+ createQueryRows ( equalsQueryRows ) ;
428+ QueryModal . testQuery ( ) ;
429+ QueryModal . waitForQueryTestToFinish ( ) ;
430+ QueryModal . getQueryAreaContent ( ) . then ( ( actualPreviewQuery ) => {
431+ actualQueries . preview = actualPreviewQuery ;
432+ } ) ;
433+ QueryModal . clickRunQueryAndSave ( ) ;
434+ QueryModal . verifyClosed ( ) ;
435+ Lists . waitForCompilingToComplete ( 3000 ) ;
436+ Lists . getQueryText ( ) . then ( ( actualSavedQuery ) => {
437+ actualQueries . saved = actualSavedQuery ;
438+ } ) ;
439+ cy . then ( ( ) => {
440+ verifyUserFriendlyQueryText ( {
441+ queryBuilderPreview : actualQueries . preview ,
442+ listDetails : actualQueries . saved ,
443+ expectedQuery : expectedEqualsQuery ,
444+ } ) ;
445+ } ) ;
446+ } ,
447+ ) ;
448+ } ) ;
449+
261450 describe ( 'Users custom fields' , ( ) => {
262451 const recordType = 'Users' ;
263452 const testNumber = 'C831970' ;
0 commit comments