Skip to content

Commit f64d10b

Browse files
committed
jest
1 parent d1db558 commit f64d10b

15 files changed

Lines changed: 301 additions & 22 deletions

packages/components/package-lock.json

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/components/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@labkey/components",
3-
"version": "7.13.0-fb-mvtc.21",
3+
"version": "7.13.0-fb-mvtc.22",
44
"description": "Components, models, actions, and utility functions for LabKey applications and pages",
55
"sideEffects": false,
66
"files": [
@@ -50,7 +50,7 @@
5050
"homepage": "https://github.com/LabKey/labkey-ui-components#readme",
5151
"dependencies": {
5252
"@hello-pangea/dnd": "18.0.1",
53-
"@labkey/api": "1.45.0-fb-mvtc.4",
53+
"@labkey/api": "1.45.0-fb-mvtc.5",
5454
"@testing-library/dom": "~10.4.1",
5555
"@testing-library/jest-dom": "~6.9.1",
5656
"@testing-library/react": "~16.3.0",

packages/components/src/internal/components/domainproperties/AdvancedSettings.test.tsx

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {
2121
DOMAIN_FIELD_UNIQUECONSTRAINT,
2222
DOMAIN_LAST_ENTERED_DEFAULT,
2323
DOMAIN_NON_EDITABLE_DEFAULT,
24-
INT_RANGE_URI,
24+
INT_RANGE_URI, MULTI_CHOICE_RANGE_URI,
2525
PHILEVEL_FULL_PHI,
2626
PHILEVEL_LIMITED_PHI,
2727
} from './constants';
@@ -226,4 +226,38 @@ describe('AdvancedSettings', () => {
226226
id = createFormInputId(DOMAIN_FIELD_SHOWNINDETAILSVIEW, _domainIndex, _index);
227227
expect(document.querySelectorAll('#' + id)).toHaveLength(1);
228228
});
229+
230+
test('Multi-value Text Choice hidden properties', async () => {
231+
await act(async () => {
232+
renderWithAppContext(
233+
<AdvancedSettings
234+
{...props}
235+
field={DomainField.create({ ...fieldProps, rangeURI: MULTI_CHOICE_RANGE_URI })}
236+
/>
237+
);
238+
});
239+
240+
let id = createFormInputId(DOMAIN_FIELD_DEFAULT_VALUE_TYPE, _domainIndex, _index);
241+
expect(document.querySelectorAll('#' + id)).toHaveLength(1);
242+
id = createFormInputId(DOMAIN_FIELD_HIDDEN, _domainIndex, _index);
243+
expect(document.querySelectorAll('#' + id)).toHaveLength(1);
244+
id = createFormInputId(DOMAIN_FIELD_SHOWNININSERTVIEW, _domainIndex, _index);
245+
expect(document.querySelectorAll('#' + id)).toHaveLength(1);
246+
id = createFormInputId(DOMAIN_FIELD_SHOWNINUPDATESVIEW, _domainIndex, _index);
247+
expect(document.querySelectorAll('#' + id)).toHaveLength(1);
248+
id = createFormInputId(DOMAIN_FIELD_SHOWNINDETAILSVIEW, _domainIndex, _index);
249+
expect(document.querySelectorAll('#' + id)).toHaveLength(1);
250+
id = createFormInputId(DOMAIN_FIELD_PHI, _domainIndex, _index);
251+
expect(document.querySelectorAll('#' + id)).toHaveLength(1);
252+
id = createFormInputId(DOMAIN_FIELD_CONSTRAINT, _domainIndex, _index);
253+
expect(document.querySelectorAll('#' + id)).toHaveLength(0);
254+
id = createFormInputId(DOMAIN_FIELD_MEASURE, _domainIndex, _index);
255+
expect(document.querySelectorAll('#' + id)).toHaveLength(0);
256+
id = createFormInputId(DOMAIN_FIELD_DIMENSION, _domainIndex, _index);
257+
expect(document.querySelectorAll('#' + id)).toHaveLength(0);
258+
id = createFormInputId(DOMAIN_FIELD_MVENABLED, _domainIndex, _index);
259+
expect(document.querySelectorAll('#' + id)).toHaveLength(0);
260+
id = createFormInputId(DOMAIN_FIELD_RECOMMENDEDVARIABLE, _domainIndex, _index);
261+
expect(document.querySelectorAll('#' + id)).toHaveLength(0);
262+
});
229263
});

packages/components/src/internal/components/domainproperties/CalculatedFieldOptions.test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ describe('CalculatedFieldOptions', () => {
123123
List.of(
124124
{ name: 'b', dataType: { name: 'text' } } as DomainField,
125125
{ name: 'c', dataType: { name: 'calculation' } } as DomainField,
126+
{ name: 'c', dataType: { name: 'multiChoice' } } as DomainField,
126127
{ name: 'd', dataType: { name: 'INT' } } as DomainField
127128
),
128129
[{ Name: 'a', DataType: 'integer' } as SystemField]

packages/components/src/internal/components/domainproperties/DomainRowExpandedOptions.test.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
DATETIME_TYPE,
1515
DOUBLE_TYPE,
1616
FLAG_TYPE,
17-
INTEGER_TYPE,
17+
INTEGER_TYPE, MULTI_CHOICE_TYPE,
1818
MULTILINE_TYPE,
1919
ONTOLOGY_LOOKUP_TYPE,
2020
SAMPLE_TYPE,
@@ -241,6 +241,21 @@ describe('DomainRowExpandedOptions', () => {
241241
});
242242
});
243243

244+
test('Multi-Value Text Choice data type', async () => {
245+
const field = DomainField.create({
246+
rangeURI: MULTI_CHOICE_TYPE.rangeURI,
247+
});
248+
249+
render(<DomainRowExpandedOptions {...DEFAULT_PROPS} field={field} />);
250+
251+
await waitFor(() => {
252+
const headers = document.querySelectorAll('.domain-field-section-heading');
253+
expect(headers.length).toBe(2);
254+
expect(headers[0].textContent).toBe('Text Choice Options');
255+
expect(headers[1].textContent).toBe('Name and Linking Options');
256+
});
257+
});
258+
244259
test('Calculation data type, text', async () => {
245260
const field = DomainField.create({
246261
conceptURI: CALCULATED_TYPE.conceptURI,

packages/components/src/internal/components/domainproperties/PropDescType.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ export class PropDescType
158158
// TODO should this change to default to returning this.name and just catch the diff cases?
159159
switch (this.name) {
160160
case 'array':
161+
case 'multiChoice':
161162
return 'array';
162163
case 'boolean':
163164
return 'boolean';

packages/components/src/internal/components/domainproperties/models.test.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import {
4141
PropDescType,
4242
SAMPLE_TYPE,
4343
TEXT_CHOICE_TYPE,
44+
MULTI_CHOICE_TYPE,
4445
TEXT_TYPE,
4546
TIME_TYPE,
4647
UNIQUE_ID_TYPE,
@@ -287,6 +288,7 @@ describe('PropDescType', () => {
287288
expect(PropDescType.isInteger(PARTICIPANT_TYPE.rangeURI)).toBeFalsy();
288289
expect(PropDescType.isInteger(ONTOLOGY_LOOKUP_TYPE.rangeURI)).toBeFalsy();
289290
expect(PropDescType.isInteger(TEXT_CHOICE_TYPE.rangeURI)).toBeFalsy();
291+
expect(PropDescType.isInteger(MULTI_CHOICE_TYPE.rangeURI)).toBeFalsy();
290292
});
291293

292294
test('isString', () => {
@@ -305,6 +307,7 @@ describe('PropDescType', () => {
305307
expect(PropDescType.isString(PARTICIPANT_TYPE.rangeURI)).toBeTruthy();
306308
expect(PropDescType.isString(ONTOLOGY_LOOKUP_TYPE.rangeURI)).toBeTruthy();
307309
expect(PropDescType.isString(TEXT_CHOICE_TYPE.rangeURI)).toBeTruthy();
310+
expect(PropDescType.isString(MULTI_CHOICE_TYPE.rangeURI)).toBeFalsy();
308311
});
309312

310313
test('isNumeric', () => {
@@ -323,6 +326,7 @@ describe('PropDescType', () => {
323326
expect(PropDescType.isNumeric(PARTICIPANT_TYPE.rangeURI)).toBeFalsy();
324327
expect(PropDescType.isNumeric(ONTOLOGY_LOOKUP_TYPE.rangeURI)).toBeFalsy();
325328
expect(PropDescType.isNumeric(TEXT_CHOICE_TYPE.rangeURI)).toBeFalsy();
329+
expect(PropDescType.isNumeric(MULTI_CHOICE_TYPE.rangeURI)).toBeFalsy();
326330
});
327331

328332
test('isMeasure', () => {
@@ -341,6 +345,7 @@ describe('PropDescType', () => {
341345
expect(PropDescType.isMeasure(PARTICIPANT_TYPE.rangeURI)).toBeTruthy();
342346
expect(PropDescType.isMeasure(ONTOLOGY_LOOKUP_TYPE.rangeURI)).toBeTruthy();
343347
expect(PropDescType.isMeasure(TEXT_CHOICE_TYPE.rangeURI)).toBeTruthy();
348+
expect(PropDescType.isMeasure(MULTI_CHOICE_TYPE.rangeURI)).toBeFalsy();
344349
});
345350

346351
test('isDimension', () => {
@@ -359,6 +364,7 @@ describe('PropDescType', () => {
359364
expect(PropDescType.isDimension(PARTICIPANT_TYPE.rangeURI)).toBeTruthy();
360365
expect(PropDescType.isDimension(ONTOLOGY_LOOKUP_TYPE.rangeURI)).toBeTruthy();
361366
expect(PropDescType.isDimension(TEXT_CHOICE_TYPE.rangeURI)).toBeTruthy();
367+
expect(PropDescType.isDimension(MULTI_CHOICE_TYPE.rangeURI)).toBeFalsy();
362368
});
363369

364370
test('isMvEnableable', () => {
@@ -377,6 +383,7 @@ describe('PropDescType', () => {
377383
expect(PropDescType.isMvEnableable(PARTICIPANT_TYPE.rangeURI)).toBeTruthy();
378384
expect(PropDescType.isMvEnableable(ONTOLOGY_LOOKUP_TYPE.rangeURI)).toBeTruthy();
379385
expect(PropDescType.isMvEnableable(TEXT_CHOICE_TYPE.rangeURI)).toBeTruthy();
386+
expect(PropDescType.isMvEnableable(MULTI_CHOICE_TYPE.rangeURI)).toBeFalsy();
380387
});
381388

382389
test('isUser', () => {
@@ -405,10 +412,22 @@ describe('PropDescType', () => {
405412
expect(PropDescType.isTextChoice(null)).toBeFalsy();
406413
expect(PropDescType.isTextChoice(SAMPLE_TYPE_CONCEPT_URI)).toBeFalsy();
407414
expect(PropDescType.isTextChoice(TEXT_CHOICE_CONCEPT_URI)).toBeTruthy();
415+
expect(PropDescType.isTextChoice(MULTI_CHOICE_TYPE.rangeURI)).toBeFalsy();
408416
expect(PropDescType.isTextChoice('testing')).toBeFalsy();
409417
expect(PropDescType.isTextChoice('textChoice')).toBeTruthy();
410418
});
411419

420+
test('isMultiChoice', () => {
421+
expect(PropDescType.isMultiChoice(undefined)).toBeFalsy();
422+
expect(PropDescType.isMultiChoice(null)).toBeFalsy();
423+
expect(PropDescType.isMultiChoice(SAMPLE_TYPE_CONCEPT_URI)).toBeFalsy();
424+
expect(PropDescType.isMultiChoice(TEXT_CHOICE_CONCEPT_URI)).toBeFalsy();
425+
expect(PropDescType.isMultiChoice(MULTI_CHOICE_TYPE.rangeURI)).toBeTruthy();
426+
expect(PropDescType.isMultiChoice('testing')).toBeFalsy();
427+
expect(PropDescType.isMultiChoice('textChoice')).toBeFalsy();
428+
expect(PropDescType.isMultiChoice('multiChoice')).toBeTruthy();
429+
});
430+
412431
test('isUniqueIdField', () => {
413432
expect(PropDescType.isUniqueIdField(undefined)).toBeFalsy();
414433
expect(PropDescType.isUniqueIdField(null)).toBeFalsy();
@@ -460,6 +479,7 @@ describe('PropDescType', () => {
460479
expect(INTEGER_TYPE.getJsonType()).toBe('int');
461480
expect(DOUBLE_TYPE.getJsonType()).toBe('float');
462481
expect(DATETIME_TYPE.getJsonType()).toBe('date');
482+
expect(MULTI_CHOICE_TYPE.getJsonType()).toBe('array');
463483
});
464484

465485
test('isPropertyTypeAllowed', () => {
@@ -1068,10 +1088,10 @@ describe('DomainField', () => {
10681088
);
10691089
});
10701090

1071-
test('getDetailsTextArray, textChoiceValidator', () => {
1091+
function verifyGetDetailsTextChoiceArray(dataType: PropDescType) {
10721092
let field = DomainField.create({ propertyId: undefined, name: 'test' });
10731093
field = field.merge({
1074-
dataType: TEXT_CHOICE_TYPE,
1094+
dataType,
10751095
textChoiceValidator: DEFAULT_TEXT_CHOICE_VALIDATOR,
10761096
}) as DomainField;
10771097
expect(field.getDetailsArray().join('')).toBe('New Field. ');
@@ -1136,6 +1156,14 @@ describe('DomainField', () => {
11361156
expect(fieldSaved.getDetailsArray().join('')).toBe(
11371157
'Note: These text choice options are visible to all administrators, including those not granted any PHI reader role.'
11381158
);
1159+
}
1160+
1161+
test('getDetailsTextArray, text Choice', () => {
1162+
verifyGetDetailsTextChoiceArray(TEXT_CHOICE_TYPE);
1163+
});
1164+
1165+
test('getDetailsTextArray, multi-value text Choice', () => {
1166+
verifyGetDetailsTextChoiceArray(MULTI_CHOICE_TYPE);
11391167
});
11401168

11411169
test('getDetailsTextArray, queryMetadata editor', () => {

packages/components/src/internal/components/domainproperties/models.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ import {
8080
FILE_TYPE,
8181
FLAG_TYPE,
8282
INTEGER_TYPE,
83-
LOOKUP_TYPE,
83+
LOOKUP_TYPE, MULTI_CHOICE_TYPE,
8484
ONTOLOGY_LOOKUP_TYPE,
8585
PROP_DESC_TYPES,
8686
PropDescType,
@@ -811,7 +811,7 @@ export class PropertyValidator
811811
if (rawPropertyValidator[i].type === type) {
812812
const expressionStr = rawPropertyValidator[i].expression;
813813
const hasExpressionStr = expressionStr !== undefined && expressionStr !== null;
814-
const isChoice = type === 'TextChoice' || type === 'MultiChoice';
814+
const isChoice = type === 'TextChoice';
815815

816816
// if we are loading a textChoiceValidator from JSON, we need to set the properties.validValues
817817
if (
@@ -1228,6 +1228,10 @@ export class DomainField
12281228
field.rangeURI = raw.rangeURI;
12291229
}
12301230

1231+
if (field.dataType === MULTI_CHOICE_TYPE) {
1232+
field.rangeURI = raw.rangeURI;
1233+
}
1234+
12311235
// handle URLTarget prop casing mismatch
12321236
if (raw['urltarget'] === '_blank' || raw['URLTarget'] === '_blank') {
12331237
field.isTargetBlank = true;
@@ -1797,6 +1801,7 @@ function resolveDataType(rawField: Partial<IDomainField>): PropDescType {
17971801
if (rawField.conceptURI === SAMPLE_TYPE_CONCEPT_URI) return SAMPLE_TYPE;
17981802
if (rawField.conceptURI === SMILES_CONCEPT_URI) return SMILES_TYPE;
17991803
if (rawField.conceptURI === CALCULATED_CONCEPT_URI) return CALCULATED_TYPE;
1804+
if (rawField.rangeURI === MULTI_CHOICE_RANGE_URI) return MULTI_CHOICE_TYPE;
18001805

18011806
if (rawField.dataType) {
18021807
return rawField.dataType;

packages/components/src/internal/components/editable/actions.test.ts

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import { CellMessage, EditorModel, ValueDescriptor } from './models';
3333
import { genCellKey } from './utils';
3434
import sampleSetQueryInfoJSON from '../../../test/data/sampleSetAllFieldTypes-getQueryDetails.json';
3535
import { MockEditableGridLoader } from './utils.test';
36+
import {MULTI_CHOICE_TYPE} from "../domainproperties/PropDescType";
3637

3738
describe('column mutation actions', () => {
3839
const queryInfo = QueryInfo.fromJsonForTests(sampleSet2QueryInfo);
@@ -828,6 +829,7 @@ describe('insertPastedData', () => {
828829
const fkOne = 'field_one';
829830
const fkTwo = 'field_two';
830831
const dateFk = 'date';
832+
const mvtc = 'mvtc';
831833
const queryInfo = QueryInfo.fromJsonForTests({
832834
pkCols: [pkFk],
833835
columns: {
@@ -852,6 +854,13 @@ describe('insertPastedData', () => {
852854
inputType: 'string',
853855
jsonType: 'date',
854856
}),
857+
[mvtc]: new QueryColumn({
858+
caption: 'Multi Value TC',
859+
fieldKey: mvtc,
860+
jsonType: 'ARRAY',
861+
rangeURI: MULTI_CHOICE_TYPE.rangeURI,
862+
validValues: ['a', 'ab', 'cc', 'cD', 'A,B', 'de'],
863+
}),
855864
},
856865
});
857866

@@ -932,9 +941,19 @@ describe('insertPastedData', () => {
932941
raw: '2025-04-23',
933942
},
934943
]),
944+
[genCellKey(mvtc, 0)]: List<ValueDescriptor>([
945+
{
946+
"raw": "a",
947+
"display": "a"
948+
},
949+
{
950+
"raw": "cD",
951+
"display": "cD"
952+
}
953+
]),
935954
}),
936-
orderedColumns: List([fkOne, fkTwo, dateFk]),
937-
columnMap: [fkOne, fkTwo, dateFk].reduce((result, key) => {
955+
orderedColumns: List([fkOne, fkTwo, dateFk, mvtc]),
956+
columnMap: [fkOne, fkTwo, dateFk, mvtc].reduce((result, key) => {
938957
return result.set(key, queryInfo.getColumn(key));
939958
}, Map<string, QueryColumn>()),
940959
queryInfo,
@@ -1116,6 +1135,39 @@ describe('insertPastedData', () => {
11161135
List([{ display: '2025-04-24', raw: '2025-04-24 00:00:00.000' }])
11171136
);
11181137
});
1138+
1139+
test('pasting multi values', async () => {
1140+
const em = baseEditorModel.applyChanges({
1141+
selectionCells: [genCellKey(mvtc, 0)],
1142+
selectedColIdx: 3,
1143+
selectedRowIdx: 0,
1144+
});
1145+
const changes = await validateAndInsertPastedData(
1146+
em,
1147+
'"A,B",cD\nde,cc\nab,bad',
1148+
undefined,
1149+
true,
1150+
true,
1151+
undefined,
1152+
true
1153+
);
1154+
const cellValues = changes.cellValues;
1155+
expect(cellValues.get(genCellKey(mvtc, 0))).toEqual(
1156+
List([{ display: 'A,B', raw: 'A,B' }, { display: 'cD', raw: 'cD' }])
1157+
);
1158+
expect(cellValues.get(genCellKey(mvtc, 1))).toEqual(
1159+
List([{ display: 'cc', raw: 'cc' }, { display: 'de', raw: 'de' }])
1160+
);
1161+
expect(cellValues.get(genCellKey(mvtc, 2))).toEqual(
1162+
List([{ display: 'ab', raw: 'ab' }, { display: 'bad', raw: 'bad' }])
1163+
);
1164+
const cellMessages = changes.cellMessages;
1165+
expect(cellMessages.get(genCellKey(mvtc, 0))).toBeUndefined();
1166+
expect(cellMessages.get(genCellKey(mvtc, 1))).toBeUndefined();
1167+
expect(cellMessages.get(genCellKey(mvtc, 2))).toEqual(
1168+
{message: 'Could not find "bad"' }
1169+
);
1170+
});
11191171
});
11201172

11211173
describe('loadEditorModelData', () => {

0 commit comments

Comments
 (0)