2021-06-23 16:21:32 +02:00
use std ::collections ::HashMap ;
use once_cell ::sync ::Lazy ;
2023-09-11 16:50:53 +02:00
use crate ::common ::{ Server , Value } ;
use crate ::json ;
2021-06-23 16:21:32 +02:00
static DEFAULT_SETTINGS_VALUES : Lazy < HashMap < & 'static str , Value > > = Lazy ::new ( | | {
let mut map = HashMap ::new ( ) ;
map . insert ( " displayed_attributes " , json! ( [ " * " ] ) ) ;
map . insert ( " searchable_attributes " , json! ( [ " * " ] ) ) ;
map . insert ( " filterable_attributes " , json! ( [ ] ) ) ;
2023-09-11 16:50:53 +02:00
map . insert ( " distinct_attribute " , json! ( null ) ) ;
2021-06-24 16:25:52 +02:00
map . insert (
" ranking_rules " ,
2022-10-20 18:00:07 +02:00
json! ( [ " words " , " typo " , " proximity " , " attribute " , " sort " , " exactness " ] ) ,
2021-06-24 16:25:52 +02:00
) ;
2021-06-23 16:21:32 +02:00
map . insert ( " stop_words " , json! ( [ ] ) ) ;
2023-07-19 18:15:48 +02:00
map . insert ( " non_separator_tokens " , json! ( [ ] ) ) ;
map . insert ( " separator_tokens " , json! ( [ ] ) ) ;
map . insert ( " dictionary " , json! ( [ ] ) ) ;
2021-06-23 16:21:32 +02:00
map . insert ( " synonyms " , json! ( { } ) ) ;
2022-06-08 18:03:56 +02:00
map . insert (
" faceting " ,
json! ( {
2022-06-15 15:53:43 +02:00
" maxValuesPerFacet " : json ! ( 100 ) ,
2023-06-27 15:31:11 +02:00
" sortFacetValuesBy " : {
" * " : " alpha "
}
2022-06-15 15:53:43 +02:00
} ) ,
) ;
map . insert (
" pagination " ,
json! ( {
2022-06-22 17:24:25 +02:00
" maxTotalHits " : json ! ( 1000 ) ,
2022-06-08 18:03:56 +02:00
} ) ,
) ;
2024-03-18 12:06:00 +01:00
map . insert ( " search_cutoff_ms " , json! ( null ) ) ;
2021-06-23 16:21:32 +02:00
map
} ) ;
2021-02-24 09:30:51 +01:00
#[ actix_rt::test ]
async fn get_settings_unexisting_index ( ) {
let server = Server ::new ( ) . await ;
2021-09-28 18:10:09 +02:00
let ( response , code ) = server . index ( " test " ) . settings ( ) . await ;
assert_eq! ( code , 404 , " {} " , response )
2021-02-24 09:30:51 +01:00
}
#[ actix_rt::test ]
async fn get_settings ( ) {
let server = Server ::new ( ) . await ;
let index = server . index ( " test " ) ;
2024-03-11 18:24:21 +01:00
let ( response , _code ) = index . create ( None ) . await ;
index . wait_task ( response . uid ( ) ) . await ;
2021-02-24 09:30:51 +01:00
let ( response , code ) = index . settings ( ) . await ;
assert_eq! ( code , 200 ) ;
let settings = response . as_object ( ) . unwrap ( ) ;
2024-03-11 18:24:21 +01:00
assert_eq! ( settings . keys ( ) . len ( ) , 16 ) ;
2021-02-24 09:30:51 +01:00
assert_eq! ( settings [ " displayedAttributes " ] , json! ( [ " * " ] ) ) ;
assert_eq! ( settings [ " searchableAttributes " ] , json! ( [ " * " ] ) ) ;
2021-06-03 23:47:16 +02:00
assert_eq! ( settings [ " filterableAttributes " ] , json! ( [ ] ) ) ;
2021-08-24 15:46:14 +02:00
assert_eq! ( settings [ " sortableAttributes " ] , json! ( [ ] ) ) ;
2021-04-20 12:07:22 +02:00
assert_eq! ( settings [ " distinctAttribute " ] , json! ( null ) ) ;
2021-03-15 18:11:10 +01:00
assert_eq! (
settings [ " rankingRules " ] ,
2022-10-20 18:00:07 +02:00
json! ( [ " words " , " typo " , " proximity " , " attribute " , " sort " , " exactness " ] )
2021-03-15 18:11:10 +01:00
) ;
2021-04-06 15:43:27 +02:00
assert_eq! ( settings [ " stopWords " ] , json! ( [ ] ) ) ;
2023-07-25 10:55:37 +02:00
assert_eq! ( settings [ " nonSeparatorTokens " ] , json! ( [ ] ) ) ;
assert_eq! ( settings [ " separatorTokens " ] , json! ( [ ] ) ) ;
2023-07-19 18:15:48 +02:00
assert_eq! ( settings [ " dictionary " ] , json! ( [ ] ) ) ;
2022-06-08 18:03:56 +02:00
assert_eq! (
settings [ " faceting " ] ,
json! ( {
2022-06-09 10:17:55 +02:00
" maxValuesPerFacet " : 100 ,
2023-06-27 15:31:11 +02:00
" sortFacetValuesBy " : {
" * " : " alpha "
}
2022-06-09 10:17:55 +02:00
} )
) ;
assert_eq! (
settings [ " pagination " ] ,
json! ( {
2022-06-22 17:24:25 +02:00
" maxTotalHits " : 1000 ,
2022-06-08 18:03:56 +02:00
} )
) ;
2024-01-08 11:09:37 +01:00
assert_eq! ( settings [ " proximityPrecision " ] , json! ( " byWord " ) ) ;
2024-03-18 12:06:00 +01:00
assert_eq! ( settings [ " searchCutoffMs " ] , json! ( null ) ) ;
2021-02-24 09:30:51 +01:00
}
2024-03-26 10:36:56 +01:00
#[ actix_rt::test ]
async fn secrets_are_hidden_in_settings ( ) {
let server = Server ::new ( ) . await ;
let ( response , code ) = server . set_features ( json! ( { " vectorStore " : true } ) ) . await ;
meili_snap ::snapshot! ( code , @ " 200 OK " ) ;
meili_snap ::snapshot! ( meili_snap ::json_string! ( response ) , @ r ###"
{
" vectorStore " : true ,
" metrics " : false ,
2024-07-09 11:15:57 +02:00
" logsRoute " : false ,
2024-07-17 11:13:37 +02:00
" editDocumentsByFunction " : false ,
" containsFilter " : false
2024-03-26 10:36:56 +01:00
}
" ###);
let index = server . index ( " test " ) ;
let ( response , _code ) = index . create ( None ) . await ;
index . wait_task ( response . uid ( ) ) . await ;
let ( response , code ) = index
. update_settings ( json! ( {
" embedders " : {
" default " : {
" source " : " rest " ,
" url " : " https://localhost:7777 " ,
2024-04-03 19:10:19 +02:00
" apiKey " : " My super secret value you will never guess " ,
" dimensions " : 4 ,
2024-06-12 18:27:03 +02:00
" request " : " {{text}} " ,
" response " : " {{embedding}} "
2024-03-26 10:36:56 +01:00
}
}
} ) )
. await ;
meili_snap ::snapshot! ( code , @ " 202 Accepted " ) ;
meili_snap ::snapshot! ( meili_snap ::json_string! ( response , { " .duration " = > " [duration] " , " .enqueuedAt " = > " [date] " , " .startedAt " = > " [date] " , " .finishedAt " = > " [date] " } ) ,
@ r ###"
{
" taskUid " : 1 ,
" indexUid " : " test " ,
" status " : " enqueued " ,
" type " : " settingsUpdate " ,
" enqueuedAt " : " [date] "
}
" ###);
let settings_update_uid = response . uid ( ) ;
index . wait_task ( settings_update_uid ) . await ;
let ( response , code ) = index . settings ( ) . await ;
meili_snap ::snapshot! ( code , @ " 200 OK " ) ;
meili_snap ::snapshot! ( meili_snap ::json_string! ( response ) , @ r ###"
{
" displayedAttributes " : [
" * "
] ,
" searchableAttributes " : [
" * "
] ,
" filterableAttributes " : [ ] ,
" sortableAttributes " : [ ] ,
" rankingRules " : [
" words " ,
" typo " ,
" proximity " ,
" attribute " ,
" sort " ,
" exactness "
] ,
" stopWords " : [ ] ,
" nonSeparatorTokens " : [ ] ,
" separatorTokens " : [ ] ,
" dictionary " : [ ] ,
" synonyms " : { } ,
" distinctAttribute " : null ,
" proximityPrecision " : " byWord " ,
" typoTolerance " : {
" enabled " : true ,
" minWordSizeForTypos " : {
" oneTypo " : 5 ,
" twoTypos " : 9
} ,
" disableOnWords " : [ ] ,
" disableOnAttributes " : [ ]
} ,
" faceting " : {
" maxValuesPerFacet " : 100 ,
" sortFacetValuesBy " : {
" * " : " alpha "
}
} ,
" pagination " : {
" maxTotalHits " : 1000
} ,
" embedders " : {
" default " : {
" source " : " rest " ,
" apiKey " : " My suXXXXXX... " ,
2024-04-03 19:10:19 +02:00
" dimensions " : 4 ,
2024-03-26 10:36:56 +01:00
" documentTemplate " : " {% for field in fields %} {{ field.name }}: {{ field.value }} \n {% endfor %} " ,
" url " : " https://localhost:7777 " ,
2024-06-12 18:27:03 +02:00
" request " : " {{text}} " ,
" response " : " {{embedding}} "
2024-03-26 10:36:56 +01:00
}
} ,
" searchCutoffMs " : null
}
" ###);
let ( response , code ) = server . get_task ( settings_update_uid ) . await ;
meili_snap ::snapshot! ( code , @ " 200 OK " ) ;
meili_snap ::snapshot! ( meili_snap ::json_string! ( response [ " details " ] ) , @ r ###"
{
" embedders " : {
" default " : {
" source " : " rest " ,
" apiKey " : " My suXXXXXX... " ,
2024-04-16 14:51:21 +02:00
" dimensions " : 4 ,
2024-06-12 18:27:03 +02:00
" url " : " https://localhost:7777 " ,
" request " : " {{text}} " ,
" response " : " {{embedding}} "
2024-03-26 10:36:56 +01:00
}
}
}
" ###);
}
2021-02-24 09:42:36 +01:00
#[ actix_rt::test ]
2021-11-04 13:38:44 +01:00
async fn error_update_settings_unknown_field ( ) {
2021-02-24 09:42:36 +01:00
let server = Server ::new ( ) . await ;
let index = server . index ( " test " ) ;
let ( _response , code ) = index . update_settings ( json! ( { " foo " : 12 } ) ) . await ;
2021-06-22 11:10:57 +02:00
assert_eq! ( code , 400 ) ;
2021-02-24 09:42:36 +01:00
}
#[ actix_rt::test ]
async fn test_partial_update ( ) {
let server = Server ::new ( ) . await ;
let index = server . index ( " test " ) ;
2022-10-20 18:00:07 +02:00
let ( _response , _code ) = index . update_settings ( json! ( { " displayedAttributes " : [ " foo " ] } ) ) . await ;
2021-12-02 16:03:26 +01:00
index . wait_task ( 0 ) . await ;
2021-02-24 09:42:36 +01:00
let ( response , code ) = index . settings ( ) . await ;
assert_eq! ( code , 200 ) ;
2021-03-15 18:11:10 +01:00
assert_eq! ( response [ " displayedAttributes " ] , json! ( [ " foo " ] ) ) ;
assert_eq! ( response [ " searchableAttributes " ] , json! ( [ " * " ] ) ) ;
2021-02-24 09:42:36 +01:00
2022-10-20 18:00:07 +02:00
let ( _response , _ ) = index . update_settings ( json! ( { " searchableAttributes " : [ " bar " ] } ) ) . await ;
2021-12-02 16:03:26 +01:00
index . wait_task ( 1 ) . await ;
2021-02-24 09:42:36 +01:00
let ( response , code ) = index . settings ( ) . await ;
assert_eq! ( code , 200 ) ;
2021-03-15 18:11:10 +01:00
assert_eq! ( response [ " displayedAttributes " ] , json! ( [ " foo " ] ) ) ;
assert_eq! ( response [ " searchableAttributes " ] , json! ( [ " bar " ] ) ) ;
2021-02-24 09:42:36 +01:00
}
2021-02-24 10:14:36 +01:00
#[ actix_rt::test ]
2021-11-04 13:38:44 +01:00
async fn error_delete_settings_unexisting_index ( ) {
2021-02-24 10:14:36 +01:00
let server = Server ::new ( ) . await ;
let index = server . index ( " test " ) ;
2021-12-02 16:03:26 +01:00
let ( _response , code ) = index . delete_settings ( ) . await ;
assert_eq! ( code , 202 ) ;
2021-11-04 13:38:44 +01:00
2021-12-02 16:03:26 +01:00
let response = index . wait_task ( 0 ) . await ;
2021-11-04 13:38:44 +01:00
2021-12-02 16:03:26 +01:00
assert_eq! ( response [ " status " ] , " failed " ) ;
2021-02-24 10:14:36 +01:00
}
2021-02-24 10:19:22 +01:00
#[ actix_rt::test ]
async fn reset_all_settings ( ) {
let server = Server ::new ( ) . await ;
let index = server . index ( " test " ) ;
2021-06-03 20:08:31 +02:00
let documents = json! ( [
{
" id " : 1 ,
" name " : " curqui " ,
" age " : 99
}
] ) ;
let ( response , code ) = index . add_documents ( documents , None ) . await ;
assert_eq! ( code , 202 ) ;
2022-05-17 11:17:32 +02:00
assert_eq! ( response [ " taskUid " ] , 0 ) ;
2021-12-02 16:03:26 +01:00
index . wait_task ( 0 ) . await ;
2021-06-03 20:08:31 +02:00
2021-03-15 18:11:10 +01:00
index
2021-06-03 14:19:56 +02:00
. update_settings ( json! ( { " displayedAttributes " : [ " name " , " age " ] , " searchableAttributes " : [ " name " ] , " stopWords " : [ " the " ] , " filterableAttributes " : [ " age " ] , " synonyms " : { " puppy " : [ " dog " , " doggo " , " potat " ] } } ) )
2021-03-15 18:11:10 +01:00
. await ;
2021-12-02 16:03:26 +01:00
index . wait_task ( 1 ) . await ;
2021-02-24 10:19:22 +01:00
let ( response , code ) = index . settings ( ) . await ;
assert_eq! ( code , 200 ) ;
2021-06-03 20:08:31 +02:00
assert_eq! ( response [ " displayedAttributes " ] , json! ( [ " name " , " age " ] ) ) ;
assert_eq! ( response [ " searchableAttributes " ] , json! ( [ " name " ] ) ) ;
2021-04-06 18:29:38 +02:00
assert_eq! ( response [ " stopWords " ] , json! ( [ " the " ] ) ) ;
2022-10-20 18:00:07 +02:00
assert_eq! ( response [ " synonyms " ] , json! ( { " puppy " : [ " dog " , " doggo " , " potat " ] } ) ) ;
2021-06-03 23:47:16 +02:00
assert_eq! ( response [ " filterableAttributes " ] , json! ( [ " age " ] ) ) ;
2021-02-24 10:19:22 +01:00
index . delete_settings ( ) . await ;
2021-12-02 16:03:26 +01:00
index . wait_task ( 2 ) . await ;
2021-02-24 10:19:22 +01:00
let ( response , code ) = index . settings ( ) . await ;
assert_eq! ( code , 200 ) ;
2021-03-15 18:11:10 +01:00
assert_eq! ( response [ " displayedAttributes " ] , json! ( [ " * " ] ) ) ;
assert_eq! ( response [ " searchableAttributes " ] , json! ( [ " * " ] ) ) ;
2021-04-06 18:29:38 +02:00
assert_eq! ( response [ " stopWords " ] , json! ( [ ] ) ) ;
2021-06-03 23:47:16 +02:00
assert_eq! ( response [ " filterableAttributes " ] , json! ( [ ] ) ) ;
2021-06-14 14:35:40 +02:00
assert_eq! ( response [ " synonyms " ] , json! ( { } ) ) ;
2021-06-03 20:08:31 +02:00
let ( response , code ) = index . get_document ( 1 , None ) . await ;
assert_eq! ( code , 200 ) ;
assert! ( response . as_object ( ) . unwrap ( ) . get ( " age " ) . is_some ( ) ) ;
2021-02-24 10:19:22 +01:00
}
2021-02-24 09:30:51 +01:00
#[ actix_rt::test ]
async fn update_setting_unexisting_index ( ) {
let server = Server ::new ( ) . await ;
let index = server . index ( " test " ) ;
let ( _response , code ) = index . update_settings ( json! ( { } ) ) . await ;
2021-03-17 14:44:32 +01:00
assert_eq! ( code , 202 ) ;
2021-12-02 16:03:26 +01:00
let response = index . wait_task ( 0 ) . await ;
assert_eq! ( response [ " status " ] , " succeeded " ) ;
2021-02-24 09:30:51 +01:00
let ( _response , code ) = index . get ( ) . await ;
assert_eq! ( code , 200 ) ;
2021-12-02 16:03:26 +01:00
index . delete_settings ( ) . await ;
let response = index . wait_task ( 1 ) . await ;
assert_eq! ( response [ " status " ] , " succeeded " ) ;
2021-02-24 09:30:51 +01:00
}
2021-03-10 14:43:10 +01:00
#[ actix_rt::test ]
2021-11-04 13:38:44 +01:00
async fn error_update_setting_unexisting_index_invalid_uid ( ) {
2021-03-10 14:43:10 +01:00
let server = Server ::new ( ) . await ;
let index = server . index ( " test##! " ) ;
2021-09-28 18:10:09 +02:00
let ( response , code ) = index . update_settings ( json! ( { } ) ) . await ;
2023-01-11 14:31:34 +01:00
meili_snap ::snapshot! ( code , @ " 400 Bad Request " ) ;
meili_snap ::snapshot! ( meili_snap ::json_string! ( response ) , @ r ###"
{
" message " : " `test##! ` is not a valid index uid. Index uid can be an integer or a string containing only alphanumeric characters, hyphens (-) and underscores (_). " ,
" code " : " invalid_index_uid " ,
" type " : " invalid_request " ,
2023-01-19 15:48:20 +01:00
" link " : " https://docs.meilisearch.com/errors#invalid_index_uid "
2023-01-11 14:31:34 +01:00
}
" ###);
2021-03-10 14:43:10 +01:00
}
2021-02-24 09:30:51 +01:00
macro_rules ! test_setting_routes {
2022-06-15 15:53:43 +02:00
( $( $setting :ident $write_method :ident ) , * ) = > {
2021-02-24 09:30:51 +01:00
$(
mod $setting {
use crate ::common ::Server ;
2021-06-23 16:21:32 +02:00
use super ::DEFAULT_SETTINGS_VALUES ;
2021-02-24 09:30:51 +01:00
#[ actix_rt::test ]
async fn get_unexisting_index ( ) {
let server = Server ::new ( ) . await ;
let url = format! ( " /indexes/test/settings/ {} " ,
stringify! ( $setting )
. chars ( )
. map ( | c | if c = = '_' { '-' } else { c } )
. collect ::< String > ( ) ) ;
let ( _response , code ) = server . service . get ( url ) . await ;
2021-06-15 22:21:52 +02:00
assert_eq! ( code , 404 ) ;
2021-02-24 09:30:51 +01:00
}
#[ actix_rt::test ]
async fn update_unexisting_index ( ) {
let server = Server ::new ( ) . await ;
let url = format! ( " /indexes/test/settings/ {} " ,
stringify! ( $setting )
. chars ( )
. map ( | c | if c = = '_' { '-' } else { c } )
. collect ::< String > ( ) ) ;
2023-09-11 16:50:53 +02:00
let ( response , code ) = server . service . $write_method ( url , serde_json ::Value ::Null . into ( ) ) . await ;
2021-04-01 15:50:45 +02:00
assert_eq! ( code , 202 , " {} " , response ) ;
2021-12-02 16:03:26 +01:00
server . index ( " " ) . wait_task ( 0 ) . await ;
2021-03-12 00:37:43 +01:00
let ( response , code ) = server . index ( " test " ) . get ( ) . await ;
assert_eq! ( code , 200 , " {} " , response ) ;
2021-02-24 09:30:51 +01:00
}
#[ actix_rt::test ]
async fn delete_unexisting_index ( ) {
let server = Server ::new ( ) . await ;
let url = format! ( " /indexes/test/settings/ {} " ,
stringify! ( $setting )
. chars ( )
. map ( | c | if c = = '_' { '-' } else { c } )
. collect ::< String > ( ) ) ;
2021-12-02 16:03:26 +01:00
let ( _ , code ) = server . service . delete ( url ) . await ;
assert_eq! ( code , 202 ) ;
let response = server . index ( " " ) . wait_task ( 0 ) . await ;
assert_eq! ( response [ " status " ] , " failed " ) ;
2021-06-23 16:21:32 +02:00
}
#[ actix_rt::test ]
async fn get_default ( ) {
let server = Server ::new ( ) . await ;
let index = server . index ( " test " ) ;
let ( response , code ) = index . create ( None ) . await ;
2021-12-02 16:03:26 +01:00
assert_eq! ( code , 202 , " {} " , response ) ;
index . wait_task ( 0 ) . await ;
2021-06-23 16:21:32 +02:00
let url = format! ( " /indexes/test/settings/ {} " ,
stringify! ( $setting )
. chars ( )
. map ( | c | if c = = '_' { '-' } else { c } )
. collect ::< String > ( ) ) ;
let ( response , code ) = server . service . get ( url ) . await ;
assert_eq! ( code , 200 , " {} " , response ) ;
let expected = DEFAULT_SETTINGS_VALUES . get ( stringify! ( $setting ) ) . unwrap ( ) ;
assert_eq! ( expected , & response ) ;
2021-02-24 09:30:51 +01:00
}
}
) *
} ;
}
test_setting_routes! (
2022-06-15 15:53:43 +02:00
filterable_attributes put ,
displayed_attributes put ,
searchable_attributes put ,
distinct_attribute put ,
stop_words put ,
2023-08-08 16:03:16 +02:00
separator_tokens put ,
non_separator_tokens put ,
dictionary put ,
2022-06-15 15:53:43 +02:00
ranking_rules put ,
synonyms put ,
pagination patch ,
2024-03-12 18:19:02 +01:00
faceting patch ,
2024-03-18 12:06:00 +01:00
search_cutoff_ms put
2021-03-15 18:11:10 +01:00
) ;
2021-11-04 13:38:44 +01:00
#[ actix_rt::test ]
async fn error_set_invalid_ranking_rules ( ) {
let server = Server ::new ( ) . await ;
let index = server . index ( " test " ) ;
index . create ( None ) . await ;
2023-01-11 12:33:56 +01:00
let ( response , code ) = index . update_settings ( json! ( { " rankingRules " : [ " manyTheFish " ] } ) ) . await ;
2023-01-11 14:31:34 +01:00
meili_snap ::snapshot! ( code , @ " 400 Bad Request " ) ;
meili_snap ::snapshot! ( meili_snap ::json_string! ( response ) , @ r ###"
2023-01-11 12:33:56 +01:00
{
2023-01-12 13:55:53 +01:00
" message " : " Invalid value at `.rankingRules[0]`: `manyTheFish` ranking rule is invalid. Valid ranking rules are words, typo, sort, proximity, attribute, exactness and custom ranking rules. " ,
2023-01-11 12:33:56 +01:00
" code " : " invalid_settings_ranking_rules " ,
" type " : " invalid_request " ,
2023-01-19 15:48:20 +01:00
" link " : " https://docs.meilisearch.com/errors#invalid_settings_ranking_rules "
2023-01-11 12:33:56 +01:00
}
" ###);
2021-11-04 13:38:44 +01:00
}
#[ actix_rt::test ]
async fn set_and_reset_distinct_attribute_with_dedicated_route ( ) {
let server = Server ::new ( ) . await ;
let index = server . index ( " test " ) ;
let ( _response , _code ) = index . update_distinct_attribute ( json! ( " test " ) ) . await ;
2021-12-02 16:03:26 +01:00
index . wait_task ( 0 ) . await ;
2021-11-04 13:38:44 +01:00
let ( response , _ ) = index . get_distinct_attribute ( ) . await ;
assert_eq! ( response , " test " ) ;
index . update_distinct_attribute ( json! ( null ) ) . await ;
2021-12-02 16:03:26 +01:00
index . wait_task ( 1 ) . await ;
2021-11-04 13:38:44 +01:00
let ( response , _ ) = index . get_distinct_attribute ( ) . await ;
assert_eq! ( response , json! ( null ) ) ;
}