@@ -317,7 +317,7 @@ describe('Import with update / merge', () => {
317
317
it ( "Issue 52922: Blank sample id in the file are getting ignored in update from file" , async ( ) => {
318
318
const BLANK_KEY_UPDATE_ERROR = 'Name value not provided on row ' ;
319
319
const BLANK_KEY_MERGE_ERROR_NO_EXPRESSION = 'SampleID or Name is required for sample on row' ;
320
- const BOGUS_KEY_UPDATE_ERROR = 'Sample does not exist : bogus.' ;
320
+ const BOGUS_KEY_UPDATE_ERROR = 'Sample not found : bogus.' ;
321
321
const CROSS_FOLDER_UPDATE_NOT_SUPPORTED_ERROR = "Sample does not belong to " ;
322
322
323
323
const dataType = SAMPLE_ALIQUOT_IMPORT_NO_NAME_PATTERN_NAME ;
@@ -715,19 +715,19 @@ describe('Aliquot crud', () => {
715
715
importText = "Description\tAliquotedFrom\n" ;
716
716
importText += aliquotDesc + "\t" + absentRootSample + "\n" ;
717
717
let resp = await ExperimentCRUDUtils . importSample ( server , importText , SAMPLE_ALIQUOT_IMPORT_TYPE_NAME , "IMPORT" , topFolderOptions , editorUserOptions ) ;
718
- expect ( resp . text . indexOf ( "Aliquot parent 'Absent_Root' not found." ) > - 1 ) . toBeTruthy ( ) ;
718
+ expect ( resp . text ) . toContain ( "Aliquot parent 'Absent_Root' not found." ) ;
719
719
const invalidRootSample = "Not_This_Root" ;
720
720
await ExperimentCRUDUtils . insertSamples ( server , [ { name : invalidRootSample } ] , SAMPLE_ALIQUOT_IMPORT_TYPE_NAME , topFolderOptions , editorUserOptions )
721
721
722
722
importText = "Name\tDescription\tAliquotedFrom\n" ;
723
723
importText += aliquot01 + "\t" + aliquotDesc + "\t" + invalidRootSample + "\n" ;
724
724
// Validate that if the AliquotedFrom field has an invalid value the import fails.
725
725
resp = await ExperimentCRUDUtils . importSample ( server , importText , SAMPLE_ALIQUOT_IMPORT_TYPE_NAME , "IMPORT" , topFolderOptions , editorUserOptions ) ;
726
- expect ( resp . text . indexOf ( "duplicate key" ) > - 1 ) . toBeTruthy ( ) ;
726
+ expect ( resp . text ) . toContain ( "already exists" ) ;
727
727
728
728
// Validate that the AliquotedFrom field of an aliquot cannot be updated.
729
729
resp = await ExperimentCRUDUtils . importSample ( server , importText , SAMPLE_ALIQUOT_IMPORT_TYPE_NAME , "MERGE" , topFolderOptions , editorUserOptions ) ;
730
- expect ( resp . text . indexOf ( "Aliquot parents cannot be updated for sample testInvalidImportCasesParent1-1." ) > - 1 ) . toBeTruthy ( ) ;
730
+ expect ( resp . text ) . toContain ( "Aliquot parents cannot be updated for sample testInvalidImportCasesParent1-1." ) ;
731
731
732
732
// AliquotedFrom is ignored for UPDATE option
733
733
resp = await ExperimentCRUDUtils . importSample ( server , importText , SAMPLE_ALIQUOT_IMPORT_TYPE_NAME , "UPDATE" , topFolderOptions , editorUserOptions ) ;
@@ -746,7 +746,7 @@ describe('Aliquot crud', () => {
746
746
importText = "Name\tAliquotedFrom\n" ;
747
747
importText += invalidRootSample + "\t" + parentSampleName + "\n" ;
748
748
resp = await ExperimentCRUDUtils . importSample ( server , importText , SAMPLE_ALIQUOT_IMPORT_TYPE_NAME , "MERGE" , topFolderOptions , editorUserOptions ) ;
749
- expect ( resp . text . indexOf ( "Unable to change sample to aliquot Not_This_Root." ) > - 1 ) . toBeTruthy ( ) ;
749
+ expect ( resp . text ) . toContain ( "Unable to change sample to aliquot Not_This_Root." ) ;
750
750
} ) ;
751
751
752
752
/**
@@ -951,3 +951,135 @@ describe('Aliquot crud', () => {
951
951
952
952
} ) ;
953
953
954
+ describe ( 'Duplicate IDs' , ( ) => {
955
+ it ( "Issue 52657: We shouldn't allow creating sample names that differ only in case." , async ( ) => {
956
+ const sampleTypeName = 'Type Case Sensitive' ;
957
+ let field = { name : 'case' , rangeURI : 'http://www.w3.org/2001/XMLSchema#string' } ;
958
+ const domainPayload = {
959
+ kind : 'SampleSet' ,
960
+ domainDesign : { name : sampleTypeName , fields : [ { name : 'Name' } , field ] } ,
961
+ options : {
962
+ name : sampleTypeName ,
963
+ nameExpression : 'S-${case}'
964
+ }
965
+ } ;
966
+ await server . post ( 'property' , 'createDomain' , domainPayload , { ...topFolderOptions , ...designerReaderOptions } ) . expect ( successfulResponse ) ;
967
+
968
+ const NAME_EXIST_MSG = "The name '%%' already exists." ;
969
+ const sample1 = 'S-case-sAmple1' ;
970
+ const sample2 = 'S-case-sAmple2' ;
971
+
972
+ let insertRows = [ {
973
+ name : sample1 ,
974
+ } , {
975
+ name : sample2 ,
976
+ } ] ;
977
+ const sampleRows = await ExperimentCRUDUtils . insertSamples ( server , insertRows , sampleTypeName , topFolderOptions , editorUserOptions ) ;
978
+ const sample1RowId = caseInsensitive ( sampleRows [ 0 ] , 'rowId' ) ;
979
+ const sample1Lsid = caseInsensitive ( sampleRows [ 0 ] , 'lsid' ) ;
980
+ const sample2RowId = caseInsensitive ( sampleRows [ 1 ] , 'rowId' ) ;
981
+ const sample2Lsid = caseInsensitive ( sampleRows [ 1 ] , 'lsid' ) ;
982
+
983
+ let expectedError = NAME_EXIST_MSG . replace ( '%%' , 'S-case-sample1' ) ;
984
+ // import
985
+ let errorResp = await ExperimentCRUDUtils . importSample ( server , "Name\tDescription\nS-case-sample1\tbad\ns-case-sample2\tbad" , sampleTypeName , "IMPORT" , topFolderOptions , editorUserOptions ) ;
986
+ expect ( errorResp . text ) . toContain ( expectedError ) ;
987
+
988
+ // merge
989
+ let mergeError = 'The name \'S-case-sample1\' could not be resolved. Please check the casing of the provided name.' ;
990
+ errorResp = await ExperimentCRUDUtils . importSample ( server , "Name\tDescription\nS-case-sample1\tbad\ns-case-sample2\tbad" , sampleTypeName , "MERGE" , topFolderOptions , editorUserOptions ) ;
991
+ expect ( errorResp . text ) . toContain ( mergeError ) ;
992
+
993
+ // insert
994
+ await server . post ( 'query' , 'insertRows' , {
995
+ schemaName : 'samples' ,
996
+ queryName : sampleTypeName ,
997
+ rows : [ {
998
+ name : 'S-case-sample1' ,
999
+ } ]
1000
+ } , { ...topFolderOptions , ...editorUserOptions } ) . expect ( ( result ) => {
1001
+ const errorResp = JSON . parse ( result . text ) ;
1002
+ expect ( errorResp [ 'exception' ] ) . toBe ( expectedError ) ;
1003
+ } ) ;
1004
+
1005
+ // insert using naming expression to create case-insensitive name
1006
+ await server . post ( 'query' , 'insertRows' , {
1007
+ schemaName : 'samples' ,
1008
+ queryName : sampleTypeName ,
1009
+ rows : [ {
1010
+ case : 'case-sample1' ,
1011
+ } ]
1012
+ } , { ...topFolderOptions , ...editorUserOptions } ) . expect ( ( result ) => {
1013
+ const errorResp = JSON . parse ( result . text ) ;
1014
+ expect ( errorResp [ 'exception' ] ) . toBe ( expectedError ) ;
1015
+ } ) ;
1016
+
1017
+ // renaming sample to another sample's case-insensitive name, using rowId
1018
+ await server . post ( 'query' , 'updateRows' , {
1019
+ schemaName : 'samples' ,
1020
+ queryName : sampleTypeName ,
1021
+ rows : [ {
1022
+ name : 'S-case-sample2' ,
1023
+ rowId : sample1RowId
1024
+ } ]
1025
+ } , { ...topFolderOptions , ...editorUserOptions } ) . expect ( ( result ) => {
1026
+ errorResp = JSON . parse ( result . text ) ;
1027
+ expect ( errorResp [ 'exception' ] ) . toBe ( NAME_EXIST_MSG . replace ( '%%' , 'S-case-sample2' ) ) ;
1028
+ } ) ;
1029
+
1030
+ // renaming sample to another sample's case-insensitive name, using lsid. Currently can only be done using api
1031
+ await server . post ( 'query' , 'updateRows' , {
1032
+ schemaName : 'samples' ,
1033
+ queryName : sampleTypeName ,
1034
+ rows : [ {
1035
+ name : 'S-case-sample2' ,
1036
+ lsid : sample1Lsid
1037
+ } ]
1038
+ } , { ...topFolderOptions , ...editorUserOptions } ) . expect ( ( result ) => {
1039
+ errorResp = JSON . parse ( result . text ) ;
1040
+ expect ( errorResp [ 'exception' ] ) . toBe ( NAME_EXIST_MSG . replace ( '%%' , 'S-case-sample2' ) ) ;
1041
+ } ) ;
1042
+
1043
+ // swap names (fail)
1044
+ await server . post ( 'query' , 'updateRows' , {
1045
+ schemaName : 'samples' ,
1046
+ queryName : sampleTypeName ,
1047
+ rows : [ {
1048
+ name : 'S-case-sample2' ,
1049
+ lsid : sample1Lsid
1050
+ } , {
1051
+ name : 'S-case-sample1' ,
1052
+ lsid : sample2Lsid
1053
+ } ]
1054
+ } , { ...topFolderOptions , ...editorUserOptions } ) . expect ( ( result ) => {
1055
+ errorResp = JSON . parse ( result . text ) ;
1056
+ expect ( errorResp [ 'exception' ] ) . toBe ( NAME_EXIST_MSG . replace ( '%%' , 'S-case-sample2' ) ) ;
1057
+ } ) ;
1058
+
1059
+ await server . post ( 'query' , 'updateRows' , {
1060
+ schemaName : 'samples' ,
1061
+ queryName : sampleTypeName ,
1062
+ rows : [ {
1063
+ name : 'S-case-sample2' ,
1064
+ rowId : sample1RowId
1065
+ } , {
1066
+ name : 'S-case-sample1' ,
1067
+ rowId : sample2RowId
1068
+ } ]
1069
+ } , { ...topFolderOptions , ...editorUserOptions } ) . expect ( ( result ) => {
1070
+ errorResp = JSON . parse ( result . text ) ;
1071
+ expect ( errorResp [ 'exception' ] ) . toBe ( NAME_EXIST_MSG . replace ( '%%' , 'S-case-sample2' ) ) ;
1072
+ } ) ;
1073
+
1074
+ // renaming current sample to case-insensitive name, using rowId
1075
+ let results = await ExperimentCRUDUtils . updateSamples ( server , [ { name : 'S-CASE-sample1' , rowId : sample1RowId } ] , sampleTypeName , topFolderOptions , editorUserOptions ) ;
1076
+ expect ( caseInsensitive ( results [ 0 ] , 'Name' ) ) . toBe ( 'S-CASE-sample1' ) ;
1077
+
1078
+ // renaming current sample to case-insensitive name, using lsid
1079
+ results = await ExperimentCRUDUtils . updateSamples ( server , [ { name : 's-case-SAMPLE1' , lsid : sample1Lsid } ] , sampleTypeName , topFolderOptions , editorUserOptions ) ;
1080
+ expect ( caseInsensitive ( results [ 0 ] , 'Name' ) ) . toBe ( 's-case-SAMPLE1' ) ;
1081
+
1082
+ } ) ;
1083
+
1084
+ } )
1085
+
0 commit comments