From decce4d8e4008dd446dfe3bd977966d259f9d615 Mon Sep 17 00:00:00 2001 From: qdequele Date: Mon, 2 Mar 2020 16:53:28 +0100 Subject: [PATCH 01/11] change route `/keys/` -> `/keys`; #495 --- meilisearch-http/src/routes/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meilisearch-http/src/routes/mod.rs b/meilisearch-http/src/routes/mod.rs index e9188100a..0dde83595 100644 --- a/meilisearch-http/src/routes/mod.rs +++ b/meilisearch-http/src/routes/mod.rs @@ -113,7 +113,7 @@ pub fn load_routes(app: &mut tide::Server) { app.at("/indexes/:index/stats") .get(|ctx| into_response(stats::index_stats(ctx))); - app.at("/keys/").get(|ctx| into_response(key::list(ctx))); + app.at("/keys").get(|ctx| into_response(key::list(ctx))); app.at("/health") .get(|ctx| into_response(health::get_health(ctx))) From 4d27318b727c96d5d7b150abe2eb30a83eca12bf Mon Sep 17 00:00:00 2001 From: qdequele Date: Mon, 2 Mar 2020 16:56:11 +0100 Subject: [PATCH 02/11] remove unnecessary comment on env Opt; #491 --- meilisearch-http/src/option.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/meilisearch-http/src/option.rs b/meilisearch-http/src/option.rs index 34a036732..7fa7aa1ca 100644 --- a/meilisearch-http/src/option.rs +++ b/meilisearch-http/src/option.rs @@ -17,9 +17,9 @@ pub struct Opt { pub master_key: Option, /// This environment variable must be set to `production` if your are running in production. - /// Could be `production` or `development` - /// - `production`: Force api keys - /// - `development`: Show logs in "info" mode + not mendatory to specify the api keys + /// If the server is running in development mode more logs will be displayed, + /// and the master key can be avoided which implies that there is no security on the updates routes. + /// This is useful to debug when integrating the engine with another service. #[structopt(long, env = "MEILI_ENV", default_value = "development", possible_values = &POSSIBLE_ENV)] pub env: String, From 6016f2e94128cd6c0311b8aa2ba2fcc70f921cbe Mon Sep 17 00:00:00 2001 From: qdequele Date: Mon, 2 Mar 2020 17:13:23 +0100 Subject: [PATCH 03/11] change wording of custom ranking rules `dsc` -> `desc`; #490 --- meilisearch-core/src/database.rs | 2 +- meilisearch-core/src/settings.rs | 10 +++---- meilisearch-http/src/helpers/meilisearch.rs | 2 +- meilisearch-http/tests/common.rs | 4 +-- meilisearch-http/tests/search.rs | 26 +++++++++---------- meilisearch-http/tests/settings.rs | 12 ++++----- .../tests/settings_ranking_rules.rs | 12 ++++----- 7 files changed, 34 insertions(+), 34 deletions(-) diff --git a/meilisearch-core/src/database.rs b/meilisearch-core/src/database.rs index 3326eb9cd..650cadd5b 100644 --- a/meilisearch-core/src/database.rs +++ b/meilisearch-core/src/database.rs @@ -1065,7 +1065,7 @@ mod tests { "attribute", "wordsPosition", "exactness", - "dsc(release_date)" + "desc(release_date)" ], "searchableAttributes": ["name", "release_date"], "displayedAttributes": ["name", "release_date"] diff --git a/meilisearch-core/src/settings.rs b/meilisearch-core/src/settings.rs index 11344a833..d506258cd 100644 --- a/meilisearch-core/src/settings.rs +++ b/meilisearch-core/src/settings.rs @@ -10,7 +10,7 @@ use self::RankingRule::*; pub const DEFAULT_RANKING_RULES: [RankingRule; 6] = [Typo, Words, Proximity, Attribute, WordsPosition, Exactness]; static RANKING_RULE_REGEX: Lazy = Lazy::new(|| { - let regex = regex::Regex::new(r"(asc|dsc)\(([a-zA-Z0-9-_]*)\)").unwrap(); + let regex = regex::Regex::new(r"(asc|desc)\(([a-zA-Z0-9-_]*)\)").unwrap(); regex }); @@ -99,7 +99,7 @@ pub enum RankingRule { WordsPosition, Exactness, Asc(String), - Dsc(String), + Desc(String), } impl std::fmt::Display for RankingRule { @@ -112,7 +112,7 @@ impl std::fmt::Display for RankingRule { RankingRule::WordsPosition => f.write_str("wordsPosition"), RankingRule::Exactness => f.write_str("exactness"), RankingRule::Asc(field) => write!(f, "asc({})", field), - RankingRule::Dsc(field) => write!(f, "dsc({})", field), + RankingRule::Desc(field) => write!(f, "desc({})", field), } } } @@ -132,7 +132,7 @@ impl FromStr for RankingRule { let captures = RANKING_RULE_REGEX.captures(s).ok_or(RankingRuleConversionError)?; match (captures.get(1).map(|m| m.as_str()), captures.get(2)) { (Some("asc"), Some(field)) => RankingRule::Asc(field.as_str().to_string()), - (Some("dsc"), Some(field)) => RankingRule::Dsc(field.as_str().to_string()), + (Some("desc"), Some(field)) => RankingRule::Desc(field.as_str().to_string()), _ => return Err(RankingRuleConversionError) } } @@ -144,7 +144,7 @@ impl FromStr for RankingRule { impl RankingRule { pub fn field(&self) -> Option<&str> { match self { - RankingRule::Asc(field) | RankingRule::Dsc(field) => Some(field), + RankingRule::Asc(field) | RankingRule::Desc(field) => Some(field), _ => None, } } diff --git a/meilisearch-http/src/helpers/meilisearch.rs b/meilisearch-http/src/helpers/meilisearch.rs index 3d2b2f399..377bb1ae9 100644 --- a/meilisearch-http/src/helpers/meilisearch.rs +++ b/meilisearch-http/src/helpers/meilisearch.rs @@ -313,7 +313,7 @@ impl<'a> SearchBuilder<'a> { Err(err) => error!("Error during criteria builder; {:?}", err), } } - RankingRule::Dsc(field) => { + RankingRule::Desc(field) => { match SortByAttr::higher_is_better(&ranked_map, &schema, &field) { Ok(rule) => builder.push(rule), Err(err) => error!("Error during criteria builder; {:?}", err), diff --git a/meilisearch-http/tests/common.rs b/meilisearch-http/tests/common.rs index 605caa833..fd2f53742 100644 --- a/meilisearch-http/tests/common.rs +++ b/meilisearch-http/tests/common.rs @@ -62,9 +62,9 @@ pub fn enrich_server_with_movies_settings( "proximity", "attribute", "wordsPosition", - "dsc(popularity)", + "desc(popularity)", "exactness", - "dsc(vote_average)", + "desc(vote_average)", ], "distinctAttribute": null, "searchableAttributes": [ diff --git a/meilisearch-http/tests/search.rs b/meilisearch-http/tests/search.rs index b03ff4a0d..1bb37be8a 100644 --- a/meilisearch-http/tests/search.rs +++ b/meilisearch-http/tests/search.rs @@ -631,9 +631,9 @@ fn search_with_settings_basic() { "proximity", "attribute", "wordsPosition", - "dsc(popularity)", + "desc(popularity)", "exactness", - "dsc(vote_average)" + "desc(vote_average)" ], "distinctAttribute": null, "identifier": "id", @@ -737,9 +737,9 @@ fn search_with_settings_stop_words() { "proximity", "attribute", "wordsPosition", - "dsc(popularity)", + "desc(popularity)", "exactness", - "dsc(vote_average)" + "desc(vote_average)" ], "distinctAttribute": null, "identifier": "id", @@ -844,9 +844,9 @@ fn search_with_settings_synonyms() { "proximity", "attribute", "wordsPosition", - "dsc(popularity)", + "desc(popularity)", "exactness", - "dsc(vote_average)" + "desc(vote_average)" ], "distinctAttribute": null, "identifier": "id", @@ -958,7 +958,7 @@ fn search_with_settings_ranking_rules() { "wordsPosition", "asc(vote_average)", "exactness", - "dsc(popularity)" + "desc(popularity)" ], "distinctAttribute": null, "identifier": "id", @@ -1063,9 +1063,9 @@ fn search_with_settings_searchable_attributes() { "proximity", "attribute", "wordsPosition", - "dsc(popularity)", + "desc(popularity)", "exactness", - "dsc(vote_average)" + "desc(vote_average)" ], "distinctAttribute": null, "identifier": "id", @@ -1169,9 +1169,9 @@ fn search_with_settings_displayed_attributes() { "proximity", "attribute", "wordsPosition", - "dsc(popularity)", + "desc(popularity)", "exactness", - "dsc(vote_average)" + "desc(vote_average)" ], "distinctAttribute": null, "identifier": "id", @@ -1240,9 +1240,9 @@ fn search_with_settings_searchable_attributes_2() { "proximity", "attribute", "wordsPosition", - "dsc(popularity)", + "desc(popularity)", "exactness", - "dsc(vote_average)" + "desc(vote_average)" ], "distinctAttribute": null, "identifier": "id", diff --git a/meilisearch-http/tests/settings.rs b/meilisearch-http/tests/settings.rs index 09a8c96bd..eedd8cb53 100644 --- a/meilisearch-http/tests/settings.rs +++ b/meilisearch-http/tests/settings.rs @@ -47,8 +47,8 @@ fn write_all_and_delete() { "attribute", "wordsPosition", "exactness", - "dsc(release_date)", - "dsc(rank)", + "desc(release_date)", + "desc(rank)", ], "distinctAttribute": "movie_id", "searchableAttributes": [ @@ -198,8 +198,8 @@ fn write_all_and_update() { "attribute", "wordsPosition", "exactness", - "dsc(release_date)", - "dsc(rank)", + "desc(release_date)", + "desc(rank)", ], "distinctAttribute": "movie_id", "searchableAttributes": [ @@ -264,7 +264,7 @@ fn write_all_and_update() { "attribute", "wordsPosition", "exactness", - "dsc(release_date)", + "desc(release_date)", ], "searchableAttributes": [ "title", @@ -317,7 +317,7 @@ fn write_all_and_update() { "attribute", "wordsPosition", "exactness", - "dsc(release_date)", + "desc(release_date)", ], "distinctAttribute": null, "searchableAttributes": [ diff --git a/meilisearch-http/tests/settings_ranking_rules.rs b/meilisearch-http/tests/settings_ranking_rules.rs index 786f72dd5..66ee08393 100644 --- a/meilisearch-http/tests/settings_ranking_rules.rs +++ b/meilisearch-http/tests/settings_ranking_rules.rs @@ -45,8 +45,8 @@ fn write_all_and_delete() { "attribute", "wordsPosition", "exactness", - "dsc(release_date)", - "dsc(rank)", + "desc(release_date)", + "desc(rank)", ]); let body = json.to_string().into_bytes(); @@ -143,8 +143,8 @@ fn write_all_and_update() { "attribute", "wordsPosition", "exactness", - "dsc(release_date)", - "dsc(rank)", + "desc(release_date)", + "desc(rank)", ]); let body = json.to_string().into_bytes(); @@ -180,7 +180,7 @@ fn write_all_and_update() { "attribute", "wordsPosition", "exactness", - "dsc(release_date)", + "desc(release_date)", ]); let body_update = json_update.to_string().into_bytes(); @@ -212,7 +212,7 @@ fn write_all_and_update() { "attribute", "wordsPosition", "exactness", - "dsc(release_date)", + "desc(release_date)", ]); assert_json_eq!(res_expected, res_value, ordered: false); From 81ce90e57f651a132a52a7c9c7f9189a6fbe4043 Mon Sep 17 00:00:00 2001 From: qdequele Date: Wed, 4 Mar 2020 14:18:07 +0100 Subject: [PATCH 04/11] update test --- meilisearch-http/tests/common.rs | 559 +++++++++++++----- meilisearch-http/tests/health.rs | 44 +- meilisearch-http/tests/index.rs | 314 +++------- meilisearch-http/tests/search.rs | 153 ++--- meilisearch-http/tests/settings.rs | 194 ++---- .../tests/settings_ranking_rules.rs | 152 +---- 6 files changed, 640 insertions(+), 776 deletions(-) diff --git a/meilisearch-http/tests/common.rs b/meilisearch-http/tests/common.rs index fd2f53742..190101479 100644 --- a/meilisearch-http/tests/common.rs +++ b/meilisearch-http/tests/common.rs @@ -1,10 +1,9 @@ #![allow(dead_code)] +use http::StatusCode; use serde_json::Value; -use std::error::Error; use std::time::Duration; -use assert_json_diff::assert_json_eq; use async_std::io::prelude::*; use async_std::task::{block_on, sleep}; use http_service::Body; @@ -16,171 +15,427 @@ use serde_json::json; use tempdir::TempDir; use tide::server::Service; -pub fn setup_server() -> Result>, Box> { - let tmp_dir = TempDir::new("meilisearch")?; - - let opt = Opt { - db_path: tmp_dir.path().to_str().unwrap().to_string(), - http_addr: "127.0.0.1:7700".to_owned(), - master_key: None, - env: "development".to_owned(), - no_analytics: true, - }; - - let data = Data::new(opt.clone()); - let mut app = tide::with_state(data); - routes::load_routes(&mut app); - let http_server = app.into_http_service(); - Ok(make_server(http_server)?) +pub struct Server { + uid: String, + mock: TestBackend>, } -pub fn enrich_server_with_movies_index( - server: &mut TestBackend>, -) -> Result<(), Box> { - let body = json!({ - "uid": "movies", - "identifier": "id", - }) - .to_string() - .into_bytes(); +impl Server { + pub fn with_uid(uid: &str) -> Server { + let tmp_dir = TempDir::new("meilisearch").unwrap(); - let req = http::Request::post("/indexes") - .body(Body::from(body)) - .unwrap(); - let _res = server.simulate(req).unwrap(); + let opt = Opt { + db_path: tmp_dir.path().to_str().unwrap().to_string(), + http_addr: "127.0.0.1:7700".to_owned(), + master_key: None, + env: "development".to_owned(), + no_analytics: true, + }; - Ok(()) -} + let data = Data::new(opt.clone()); + let mut app = tide::with_state(data); + routes::load_routes(&mut app); + let http_server = app.into_http_service(); + let mock = make_server(http_server).unwrap(); -pub fn enrich_server_with_movies_settings( - server: &mut TestBackend>, -) -> Result<(), Box> { - let json = json!({ - "rankingRules": [ - "typo", - "words", - "proximity", - "attribute", - "wordsPosition", - "desc(popularity)", - "exactness", - "desc(vote_average)", - ], - "distinctAttribute": null, - "searchableAttributes": [ - "title", - "tagline", - "overview", - "cast", - "director", - "producer", - "production_companies", - "genres", - ], - "displayedAttributes": [ - "title", - "director", - "producer", - "tagline", - "genres", - "id", - "overview", - "vote_count", - "vote_average", - "poster_path", - "popularity", - ], - "stopWords": null, - "synonyms": null, - "acceptNewFields": false, - }); + Server { + uid: uid.to_string(), + mock, + } + } - let body = json.to_string().into_bytes(); + fn wait_update_id(&mut self, update_id: u64) { + loop { + let req = http::Request::get(format!("/indexes/{}/updates/{}", self.uid, update_id)) + .body(Body::empty()) + .unwrap(); - let req = http::Request::post("/indexes/movies/settings") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); + let res = self.mock.simulate(req).unwrap(); + assert_eq!(res.status(), 200); - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let response: Value = serde_json::from_slice(&buf).unwrap(); + let mut buf = Vec::new(); + block_on(res.into_body().read_to_end(&mut buf)).unwrap(); + let response: Value = serde_json::from_slice(&buf).unwrap(); - assert!(response["updateId"].as_u64().is_some()); + if response["status"] == "processed" { + return; + } + block_on(sleep(Duration::from_secs(1))); + } + } - wait_update_id(server, response["updateId"].as_u64().unwrap()); + // // Global Http request GET/POST/DELETE async or sync - Ok(()) -} - -pub fn enrich_server_with_movies_documents( - server: &mut TestBackend>, -) -> Result<(), Box> { - let body = include_bytes!("assets/movies.json").to_vec(); - - let req = http::Request::post("/indexes/movies/documents") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let response: Value = serde_json::from_slice(&buf).unwrap(); - - assert!(response["updateId"].as_u64().is_some()); - - wait_update_id(server, response["updateId"].as_u64().unwrap()); - - Ok(()) -} - -pub fn search(server: &mut TestBackend>, query: &str, expect: Value) { - let req = http::Request::get(format!("/indexes/movies/search?{}", query)) - .body(Body::empty()) - .unwrap(); - let res = server.simulate(req).unwrap(); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let response: Value = serde_json::from_slice(&buf).unwrap(); - - assert_json_eq!(expect, response["hits"].clone(), ordered: false) -} - -pub fn update_config(server: &mut TestBackend>, config: Value) { - let body = config.to_string().into_bytes(); - - let req = http::Request::post("/indexes/movies/settings") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 202); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let response: Value = serde_json::from_slice(&buf).unwrap(); - - assert!(response["updateId"].as_u64().is_some()); - - wait_update_id(server, response["updateId"].as_u64().unwrap()); -} - -pub fn wait_update_id(server: &mut TestBackend>, update_id: u64) { - loop { - let req = http::Request::get(format!("/indexes/movies/updates/{}", update_id)) + fn get_request(&mut self, url: &str) -> (Value, StatusCode) { + eprintln!("get_request: {}", url); + let req = http::Request::get(url) .body(Body::empty()) .unwrap(); - - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); + let res = self.mock.simulate(req).unwrap(); + let status_code = res.status().clone(); let mut buf = Vec::new(); block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let response: Value = serde_json::from_slice(&buf).unwrap(); - - if response["status"] == "processed" { - return; - } - block_on(sleep(Duration::from_secs(1))); + let response = serde_json::from_slice(&buf).unwrap_or_default(); + (response, status_code) } + + fn post_request(&mut self, url: &str, body: Value) -> (Value, StatusCode) { + eprintln!("post_request: {}", url); + let body_bytes = body.to_string().into_bytes(); + + let req = http::Request::post(url) + .body(Body::from(body_bytes)) + .unwrap(); + let res = self.mock.simulate(req).unwrap(); + let status_code = res.status().clone(); + + let mut buf = Vec::new(); + block_on(res.into_body().read_to_end(&mut buf)).unwrap(); + let response = serde_json::from_slice(&buf).unwrap_or_default(); + (response, status_code) + } + + fn post_request_async(&mut self, url: &str, body: Value) -> (Value, StatusCode) { + eprintln!("post_request_async: {}", url); + let (response, status_code) = self.post_request(url, body); + assert_eq!(status_code, 202); + assert!(response["updateId"].as_u64().is_some()); + self.wait_update_id(response["updateId"].as_u64().unwrap()); + (response, status_code) + } + + fn put_request(&mut self, url: &str, body: Value) -> (Value, StatusCode) { + eprintln!("put_request: {}", url); + let body_bytes = body.to_string().into_bytes(); + + let req = http::Request::put(url) + .body(Body::from(body_bytes)) + .unwrap(); + let res = self.mock.simulate(req).unwrap(); + let status_code = res.status().clone(); + + let mut buf = Vec::new(); + block_on(res.into_body().read_to_end(&mut buf)).unwrap(); + let response = serde_json::from_slice(&buf).unwrap_or_default(); + (response, status_code) + } + + fn put_request_async(&mut self, url: &str, body: Value) -> (Value, StatusCode) { + eprintln!("put_request_async: {}", url); + let (response, status_code) = self.put_request(url, body); + assert!(response["updateId"].as_u64().is_some()); + assert_eq!(status_code, 202); + self.wait_update_id(response["updateId"].as_u64().unwrap()); + (response, status_code) + } + + fn delete_request(&mut self, url: &str) -> (Value, StatusCode) { + eprintln!("delete_request: {}", url); + let req = http::Request::delete(url) + .body(Body::empty()) + .unwrap(); + let res = self.mock.simulate(req).unwrap(); + let status_code = res.status().clone(); + + let mut buf = Vec::new(); + block_on(res.into_body().read_to_end(&mut buf)).unwrap(); + let response = serde_json::from_slice(&buf).unwrap_or_default(); + (response, status_code) + } + + fn delete_request_async(&mut self, url: &str) -> (Value, StatusCode) { + eprintln!("delete_request_async: {}", url); + let (response, status_code) = self.delete_request(url); + assert!(response["updateId"].as_u64().is_some()); + assert_eq!(status_code, 202); + self.wait_update_id(response["updateId"].as_u64().unwrap()); + (response, status_code) + } + + + // // All Routes + + pub fn list_indexes(&mut self) -> (Value, StatusCode) { + self.get_request("/indexes") + } + + pub fn create_index(&mut self, body: Value) -> (Value, StatusCode) { + self.post_request("/indexes", body) + } + + pub fn search_multi_index(&mut self, query: &str) -> (Value, StatusCode) { + let url = format!("/indexes/search?{}", query); + self.get_request(&url) + } + + pub fn get_index(&mut self) -> (Value, StatusCode) { + let url = format!("/indexes/{}", self.uid); + self.get_request(&url) + } + + pub fn update_index(&mut self, body: Value) -> (Value, StatusCode) { + let url = format!("/indexes/{}", self.uid); + self.put_request(&url, body) + } + + pub fn delete_index(&mut self) -> (Value, StatusCode) { + let url = format!("/indexes/{}", self.uid); + self.delete_request(&url) + } + + pub fn search(&mut self, query: &str) -> (Value, StatusCode) { + let url = format!("/indexes/{}/search?{}", self.uid, query); + self.get_request(&url) + } + + pub fn get_all_updates_status(&mut self) -> (Value, StatusCode) { + let url = format!("/indexes/{}/updates", self.uid); + self.get_request(&url) + } + + pub fn get_update_status(&mut self, update_id: u64) -> (Value, StatusCode) { + let url = format!("/indexes/{}/updates/{}", self.uid, update_id); + self.get_request(&url) + } + + pub fn get_all_documents(&mut self) -> (Value, StatusCode) { + let url = format!("/indexes/{}/documents", self.uid); + self.get_request(&url) + } + + pub fn add_or_replace_multiple_documents(&mut self, body: Value) { + let url = format!("/indexes/{}/documents", self.uid); + self.post_request_async(&url, body); + } + + pub fn add_or_update_multiple_documents(&mut self, body: Value) { + let url = format!("/indexes/{}/documents", self.uid); + self.put_request_async(&url, body); + } + + pub fn clear_all_documents(&mut self) { + let url = format!("/indexes/{}/documents", self.uid); + self.delete_request_async(&url); + } + + pub fn get_document(&mut self, document_id: u64) -> (Value, StatusCode) { + let url = format!("/indexes/{}/documents/{}", self.uid, document_id); + self.get_request(&url) + } + + pub fn delete_document(&mut self, document_id: u64) -> (Value, StatusCode) { + let url = format!("/indexes/{}/documents/{}", self.uid, document_id); + self.delete_request(&url) + } + + pub fn delete_multiple_documents(&mut self, body: Value) { + let url = format!("/indexes/{}/documents/delete-batch", self.uid); + self.post_request_async(&url, body); + } + + pub fn get_all_settings(&mut self) -> (Value, StatusCode) { + let url = format!("/indexes/{}/settings", self.uid); + self.get_request(&url) + } + + pub fn update_all_settings(&mut self, body: Value) { + let url = format!("/indexes/{}/settings", self.uid); + self.post_request_async(&url, body); + } + + pub fn delete_all_settings(&mut self) -> (Value, StatusCode) { + let url = format!("/indexes/{}/settings", self.uid); + self.delete_request_async(&url) + } + + pub fn get_ranking_rules(&mut self) -> (Value, StatusCode) { + let url = format!("/indexes/{}/settings/ranking-rules", self.uid); + self.get_request(&url) + } + + pub fn update_ranking_rules(&mut self, body: Value) { + let url = format!("/indexes/{}/settings/ranking-rules", self.uid); + self.post_request_async(&url, body); + } + + pub fn delete_ranking_rules(&mut self) -> (Value, StatusCode) { + let url = format!("/indexes/{}/settings/ranking-rules", self.uid); + self.delete_request_async(&url) + } + + pub fn get_distinct_attribute(&mut self) -> (Value, StatusCode) { + let url = format!("/indexes/{}/settings/distinct-attribute", self.uid); + self.get_request(&url) + } + + pub fn update_distinct_attribute(&mut self, body: Value) { + let url = format!("/indexes/{}/settings/distinct-attribute", self.uid); + self.post_request_async(&url, body); + } + + pub fn delete_distinct_attribute(&mut self) -> (Value, StatusCode) { + let url = format!("/indexes/{}/settings/distinct-attribute", self.uid); + self.delete_request_async(&url) + } + + pub fn get_identifier(&mut self) -> (Value, StatusCode) { + let url = format!("/indexes/{}/settings/identifier", self.uid); + self.get_request(&url) + } + + pub fn get_searchable_attributes(&mut self) -> (Value, StatusCode) { + let url = format!("/indexes/{}/settings/searchable-attributes", self.uid); + self.get_request(&url) + } + + pub fn update_searchable_attributes(&mut self, body: Value) { + let url = format!("/indexes/{}/settings/searchable-attributes", self.uid); + self.post_request_async(&url, body); + } + + pub fn delete_searchable_attributes(&mut self) -> (Value, StatusCode) { + let url = format!("/indexes/{}/settings/searchable-attributes", self.uid); + self.delete_request_async(&url) + } + + pub fn get_displayed_attributes(&mut self) -> (Value, StatusCode) { + let url = format!("/indexes/{}/settings/displayed-attributes", self.uid); + self.get_request(&url) + } + + pub fn update_displayed_attributes(&mut self, body: Value) { + let url = format!("/indexes/{}/settings/displayed-attributes", self.uid); + self.post_request_async(&url, body); + } + + pub fn delete_displayed_attributes(&mut self) -> (Value, StatusCode) { + let url = format!("/indexes/{}/settings/displayed-attributes", self.uid); + self.delete_request_async(&url) + } + + pub fn get_accept_new_fields(&mut self) -> (Value, StatusCode) { + let url = format!("/indexes/{}/settings/accept-new-fields", self.uid); + self.get_request(&url) + } + + pub fn update_accept_new_fields(&mut self, body: Value) { + let url = format!("/indexes/{}/settings/accept-new-fields", self.uid); + self.post_request_async(&url, body); + } + + pub fn get_synonyms(&mut self) -> (Value, StatusCode) { + let url = format!("/indexes/{}/settings/synonyms", self.uid); + self.get_request(&url) + } + + pub fn update_synonyms(&mut self, body: Value) { + let url = format!("/indexes/{}/settings/synonyms", self.uid); + self.post_request_async(&url, body); + } + + pub fn delete_synonyms(&mut self) -> (Value, StatusCode) { + let url = format!("/indexes/{}/settings/synonyms", self.uid); + self.delete_request_async(&url) + } + + pub fn get_stop_words(&mut self) -> (Value, StatusCode) { + let url = format!("/indexes/{}/settings/stop-words", self.uid); + self.get_request(&url) + } + + pub fn update_stop_words(&mut self, body: Value) { + let url = format!("/indexes/{}/settings/stop-words", self.uid); + self.post_request_async(&url, body); + } + + pub fn delete_stop_words(&mut self) -> (Value, StatusCode) { + let url = format!("/indexes/{}/settings/stop-words", self.uid); + self.delete_request_async(&url) + } + + pub fn get_index_stats(&mut self) -> (Value, StatusCode) { + let url = format!("/indexes/{}/stats", self.uid); + self.get_request(&url) + } + + pub fn list_keys(&mut self) -> (Value, StatusCode) { + self.get_request("/keys") + } + + pub fn get_health(&mut self) -> (Value, StatusCode) { + self.get_request("/health") + } + + pub fn update_health(&mut self, body: Value) -> (Value, StatusCode) { + self.put_request("/health", body) + } + + pub fn get_version(&mut self) -> (Value, StatusCode) { + self.get_request("/version") + } + + pub fn get_sys_info(&mut self) -> (Value, StatusCode) { + self.get_request("/sys-info") + } + + pub fn get_sys_info_pretty(&mut self) -> (Value, StatusCode) { + self.get_request("/sys-info/pretty") + } + + // Populate routes + + pub fn populate_movies(&mut self) { + let body = json!({ + "uid": "movies", + "identifier": "id", + }); + self.create_index(body); + + let body = json!({ + "rankingRules": [ + "typo", + "words", + "proximity", + "attribute", + "wordsPosition", + "desc(popularity)", + "exactness", + "desc(vote_average)", + ], + "searchableAttributes": [ + "title", + "tagline", + "overview", + "cast", + "director", + "producer", + "production_companies", + "genres", + ], + "displayedAttributes": [ + "title", + "director", + "producer", + "tagline", + "genres", + "id", + "overview", + "vote_count", + "vote_average", + "poster_path", + "popularity", + ], + "acceptNewFields": false, + }); + + self.update_all_settings(body); + + let dataset = include_bytes!("assets/movies.json"); + + let body: Value = serde_json::from_slice(dataset).unwrap(); + + self.add_or_replace_multiple_documents(body); + } + } diff --git a/meilisearch-http/tests/health.rs b/meilisearch-http/tests/health.rs index 03515891b..f41852f56 100644 --- a/meilisearch-http/tests/health.rs +++ b/meilisearch-http/tests/health.rs @@ -1,4 +1,3 @@ -use http_service::Body; use serde_json::json; use std::convert::Into; @@ -6,51 +5,34 @@ mod common; #[test] fn test_healthyness() { - let mut server = common::setup_server().unwrap(); + let mut server = common::Server::with_uid("movies"); // Check that the server is healthy - let req = http::Request::get("/health").body(Body::empty()).unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); + let (_response, status_code) = server.get_health(); + assert_eq!(status_code, 200); // Set the serve Unhealthy - let body = json!({ "health": false, - }) - .to_string() - .into_bytes(); - - let req = http::Request::put("/health") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); + }); + let (_response, status_code) = server.update_health(body); + assert_eq!(status_code, 200); // Check that the server is unhealthy - let req = http::Request::get("/health").body(Body::empty()).unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 503); + let (_response, status_code) = server.get_health(); + assert_eq!(status_code, 503); // Set the server healthy - let body = json!({ "health": true, - }) - .to_string() - .into_bytes(); - - let req = http::Request::put("/health") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); + }); + let (_response, status_code) = server.update_health(body); + assert_eq!(status_code, 200); // Check if the server is healthy - let req = http::Request::get("/health").body(Body::empty()).unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); + let (_response, status_code) = server.get_health(); + assert_eq!(status_code, 200); } diff --git a/meilisearch-http/tests/index.rs b/meilisearch-http/tests/index.rs index 464780a5f..3215cc4b0 100644 --- a/meilisearch-http/tests/index.rs +++ b/meilisearch-http/tests/index.rs @@ -1,14 +1,10 @@ -use async_std::io::prelude::*; -use async_std::task::block_on; -use http_service::Body; use serde_json::json; -use serde_json::Value; mod common; #[test] fn create_index_with_name() { - let mut server = common::setup_server().unwrap(); + let mut server = common::Server::with_uid("movies"); // 1 - Create a new index // Index with only a name "movies" @@ -16,20 +12,10 @@ fn create_index_with_name() { let body = json!({ "name": "movies", - }) - .to_string() - .into_bytes(); - - let req = http::Request::post("/indexes") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 201); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res1_value: Value = serde_json::from_slice(&buf).unwrap(); + }); + let (res1_value, status_code) = server.create_index(body); + assert_eq!(status_code, 201); assert_eq!(res1_value.as_object().unwrap().len(), 5); let r1_name = res1_value["name"].as_str().unwrap(); let r1_uid = res1_value["uid"].as_str().unwrap(); @@ -45,14 +31,8 @@ fn create_index_with_name() { // Must have 1 index with the exact same content that the request 1 // GET: /indexes - let req = http::Request::get("/indexes").body(Body::empty()).unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res2_value: Value = serde_json::from_slice(&buf).unwrap(); - + let (res2_value, status_code) = server.list_indexes(); + assert_eq!(status_code, 200); assert_eq!(res2_value.as_array().unwrap().len(), 1); assert_eq!(res2_value[0].as_object().unwrap().len(), 5); let r2_name = res2_value[0]["name"].as_str().unwrap(); @@ -68,7 +48,7 @@ fn create_index_with_name() { #[test] fn create_index_with_uid() { - let mut server = common::setup_server().unwrap(); + let mut server = common::Server::with_uid("movies"); // 1 - Create a new index // Index with only an uid "movies" @@ -76,20 +56,10 @@ fn create_index_with_uid() { let body = json!({ "uid": "movies", - }) - .to_string() - .into_bytes(); - - let req = http::Request::post("/indexes") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 201); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res1_value: Value = serde_json::from_slice(&buf).unwrap(); + }); + let (res1_value, status_code) = server.create_index(body); + assert_eq!(status_code, 201); assert_eq!(res1_value.as_object().unwrap().len(), 5); let r1_name = res1_value["name"].as_str().unwrap(); let r1_uid = res1_value["uid"].as_str().unwrap(); @@ -105,14 +75,8 @@ fn create_index_with_uid() { // Must have 1 index with the exact same content that the request 1 // GET: /indexes - let req = http::Request::get("/indexes").body(Body::empty()).unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res2_value: Value = serde_json::from_slice(&buf).unwrap(); - + let (res2_value, status_code) = server.list_indexes(); + assert_eq!(status_code, 200); assert_eq!(res2_value.as_array().unwrap().len(), 1); assert_eq!(res2_value[0].as_object().unwrap().len(), 5); let r2_name = res2_value[0]["name"].as_str().unwrap(); @@ -128,7 +92,7 @@ fn create_index_with_uid() { #[test] fn create_index_with_name_and_uid() { - let mut server = common::setup_server().unwrap(); + let mut server = common::Server::with_uid("movies"); // 1 - Create a new index // Index with a name "Films" and an uid "fn_movies" @@ -137,19 +101,9 @@ fn create_index_with_name_and_uid() { let body = json!({ "name": "Films", "uid": "fr_movies", - }) - .to_string() - .into_bytes(); - - let req = http::Request::post("/indexes") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 201); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res1_value: Value = serde_json::from_slice(&buf).unwrap(); + }); + let (res1_value, status_code) = server.create_index(body); + assert_eq!(status_code, 201); assert_eq!(res1_value.as_object().unwrap().len(), 5); let r1_name = res1_value["name"].as_str().unwrap(); @@ -166,13 +120,8 @@ fn create_index_with_name_and_uid() { // Must have 1 index with the exact same content that the request 1 // GET: /indexes - let req = http::Request::get("/indexes").body(Body::empty()).unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res2_value: Value = serde_json::from_slice(&buf).unwrap(); + let (res2_value, status_code) = server.list_indexes(); + assert_eq!(status_code, 200); assert_eq!(res2_value.as_array().unwrap().len(), 1); assert_eq!(res2_value[0].as_object().unwrap().len(), 5); @@ -189,26 +138,18 @@ fn create_index_with_name_and_uid() { #[test] fn rename_index() { - let mut server = common::setup_server().unwrap(); + let mut server = common::Server::with_uid("movies"); // 1 - Create a new index // Index with only a name "movies" // POST: /indexes let body = json!({ "name": "movies", - }) - .to_string() - .into_bytes(); + "uid": "movies", + }); - let req = http::Request::post("/indexes") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 201); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res1_value: Value = serde_json::from_slice(&buf).unwrap(); + let (res1_value, status_code) = server.create_index(body); + assert_eq!(status_code, 201); assert_eq!(res1_value.as_object().unwrap().len(), 5); let r1_name = res1_value["name"].as_str().unwrap(); @@ -217,7 +158,7 @@ fn rename_index() { let r1_updated_at = res1_value["updatedAt"].as_str().unwrap(); assert_eq!(r1_name, "movies"); - assert_eq!(r1_uid.len(), 8); + assert_eq!(r1_uid.len(), 6); assert!(r1_created_at.len() > 1); assert!(r1_updated_at.len() > 1); @@ -227,19 +168,10 @@ fn rename_index() { let body = json!({ "name": "TV Shows", - }) - .to_string() - .into_bytes(); + }); - let req = http::Request::put(format!("/indexes/{}", r1_uid)) - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res2_value: Value = serde_json::from_slice(&buf).unwrap(); + let (res2_value, status_code) = server.update_index(body); + assert_eq!(status_code, 200); assert_eq!(res2_value.as_object().unwrap().len(), 5); let r2_name = res2_value["name"].as_str().unwrap(); @@ -256,13 +188,8 @@ fn rename_index() { // Must have 1 index with the exact same content that the request 2 // GET: /indexes - let req = http::Request::get("/indexes").body(Body::empty()).unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res3_value: Value = serde_json::from_slice(&buf).unwrap(); + let (res3_value, status_code) = server.list_indexes(); + assert_eq!(status_code, 200); assert_eq!(res3_value.as_array().unwrap().len(), 1); assert_eq!(res3_value[0].as_object().unwrap().len(), 5); @@ -279,7 +206,7 @@ fn rename_index() { #[test] fn delete_index_and_recreate_it() { - let mut server = common::setup_server().unwrap(); + let mut server = common::Server::with_uid("movies"); // 1 - Create a new index // Index with only a name "movies" @@ -287,19 +214,11 @@ fn delete_index_and_recreate_it() { let body = json!({ "name": "movies", - }) - .to_string() - .into_bytes(); + "uid": "movies", + }); - let req = http::Request::post("/indexes") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 201); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res1_value: Value = serde_json::from_slice(&buf).unwrap(); + let (res1_value, status_code) = server.create_index(body); + assert_eq!(status_code, 201); assert_eq!(res1_value.as_object().unwrap().len(), 5); let r1_name = res1_value["name"].as_str().unwrap(); @@ -308,7 +227,7 @@ fn delete_index_and_recreate_it() { let r1_updated_at = res1_value["updatedAt"].as_str().unwrap(); assert_eq!(r1_name, "movies"); - assert_eq!(r1_uid.len(), 8); + assert_eq!(r1_uid.len(), 6); assert!(r1_created_at.len() > 1); assert!(r1_updated_at.len() > 1); @@ -316,13 +235,8 @@ fn delete_index_and_recreate_it() { // Must have 1 index with the exact same content that the request 1 // GET: /indexes - let req = http::Request::get("/indexes").body(Body::empty()).unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res2_value: Value = serde_json::from_slice(&buf).unwrap(); + let (res2_value, status_code) = server.list_indexes(); + assert_eq!(status_code, 200); assert_eq!(res2_value.as_array().unwrap().len(), 1); assert_eq!(res2_value[0].as_object().unwrap().len(), 5); @@ -340,27 +254,15 @@ fn delete_index_and_recreate_it() { // Update "movies" to "TV Shows" // DELETE: /indexes/:uid - let req = http::Request::delete(format!("/indexes/{}", r1_uid)) - .body(Body::empty()) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 204); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - assert_eq!(buf.len(), 0); + let (_res2_value, status_code) = server.delete_index(); + assert_eq!(status_code, 204); // 4 - Check the list of indexes // Must have 0 index // GET: /indexes - let req = http::Request::get("/indexes").body(Body::empty()).unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res2_value: Value = serde_json::from_slice(&buf).unwrap(); + let (res2_value, status_code) = server.list_indexes(); + assert_eq!(status_code, 200); assert_eq!(res2_value.as_array().unwrap().len(), 0); @@ -370,19 +272,10 @@ fn delete_index_and_recreate_it() { let body = json!({ "name": "movies", - }) - .to_string() - .into_bytes(); + }); - let req = http::Request::post("/indexes") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 201); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res1_value: Value = serde_json::from_slice(&buf).unwrap(); + let (res1_value, status_code) = server.create_index(body); + assert_eq!(status_code, 201); assert_eq!(res1_value.as_object().unwrap().len(), 5); let r1_name = res1_value["name"].as_str().unwrap(); @@ -399,13 +292,8 @@ fn delete_index_and_recreate_it() { // Must have 1 index with the exact same content that the request 1 // GET: /indexes - let req = http::Request::get("/indexes").body(Body::empty()).unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res2_value: Value = serde_json::from_slice(&buf).unwrap(); + let (res2_value, status_code) = server.list_indexes(); + assert_eq!(status_code, 200); assert_eq!(res2_value.as_array().unwrap().len(), 1); assert_eq!(res2_value[0].as_object().unwrap().len(), 5); @@ -422,7 +310,7 @@ fn delete_index_and_recreate_it() { #[test] fn check_multiples_indexes() { - let mut server = common::setup_server().unwrap(); + let mut server = common::Server::with_uid("movies"); // 1 - Create a new index // Index with only a name "movies" @@ -430,19 +318,10 @@ fn check_multiples_indexes() { let body = json!({ "name": "movies", - }) - .to_string() - .into_bytes(); + }); - let req = http::Request::post("/indexes") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 201); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res1_value: Value = serde_json::from_slice(&buf).unwrap(); + let (res1_value, status_code) = server.create_index(body); + assert_eq!(status_code, 201); assert_eq!(res1_value.as_object().unwrap().len(), 5); let r1_name = res1_value["name"].as_str().unwrap(); @@ -459,13 +338,8 @@ fn check_multiples_indexes() { // Must have 1 index with the exact same content that the request 1 // GET: /indexes - let req = http::Request::get("/indexes").body(Body::empty()).unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res2_value: Value = serde_json::from_slice(&buf).unwrap(); + let (res2_value, status_code) = server.list_indexes(); + assert_eq!(status_code, 200); assert_eq!(res2_value.as_array().unwrap().len(), 1); assert_eq!(res2_value[0].as_object().unwrap().len(), 5); @@ -485,19 +359,10 @@ fn check_multiples_indexes() { let body = json!({ "name": "films", - }) - .to_string() - .into_bytes(); + }); - let req = http::Request::post("/indexes") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 201); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res3_value: Value = serde_json::from_slice(&buf).unwrap(); + let (res3_value, status_code) = server.create_index(body); + assert_eq!(status_code, 201); assert_eq!(res3_value.as_object().unwrap().len(), 5); let r3_name = res3_value["name"].as_str().unwrap(); @@ -514,13 +379,8 @@ fn check_multiples_indexes() { // Must have 2 index with the exact same content that the request 1 and 3 // GET: /indexes - let req = http::Request::get("/indexes").body(Body::empty()).unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res4_value: Value = serde_json::from_slice(&buf).unwrap(); + let (res4_value, status_code) = server.list_indexes(); + assert_eq!(status_code, 200); assert_eq!(res4_value.as_array().unwrap().len(), 2); @@ -563,37 +423,15 @@ fn check_multiples_indexes() { #[test] fn create_index_failed() { - let mut server = common::setup_server().unwrap(); - - // 1 - Push index creation with empty body - // POST: /indexes - - let req = http::Request::post("/indexes").body(Body::empty()).unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 400); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res_value: Value = serde_json::from_slice(&buf).unwrap(); - - let message = res_value["message"].as_str().unwrap(); - assert_eq!(res_value.as_object().unwrap().len(), 1); - assert_eq!(message, "invalid data"); + let mut server = common::Server::with_uid("movies"); // 2 - Push index creation with empty json body // POST: /indexes - let body = json!({}).to_string().into_bytes(); + let body = json!({}); - let req = http::Request::post("/indexes") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 400); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res_value: Value = serde_json::from_slice(&buf).unwrap(); + let (res_value, status_code) = server.create_index(body); + assert_eq!(status_code, 400); let message = res_value["message"].as_str().unwrap(); assert_eq!(res_value.as_object().unwrap().len(), 1); @@ -605,19 +443,10 @@ fn create_index_failed() { let body = json!({ "name": "movies", "active": true - }) - .to_string() - .into_bytes(); + }); - let req = http::Request::post("/indexes") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 400); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res_value: Value = serde_json::from_slice(&buf).unwrap(); + let (res_value, status_code) = server.create_index(body); + assert_eq!(status_code, 400); let message = res_value["message"].as_str().unwrap(); assert_eq!(res_value.as_object().unwrap().len(), 1); @@ -629,19 +458,10 @@ fn create_index_failed() { let body = json!({ "name": "movies", "uid": 0 - }) - .to_string() - .into_bytes(); + }); - let req = http::Request::post("/indexes") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 400); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res_value: Value = serde_json::from_slice(&buf).unwrap(); + let (res_value, status_code) = server.create_index(body); + assert_eq!(status_code, 400); let message = res_value["message"].as_str().unwrap(); assert_eq!(res_value.as_object().unwrap().len(), 1); diff --git a/meilisearch-http/tests/search.rs b/meilisearch-http/tests/search.rs index 1bb37be8a..ddda3d24a 100644 --- a/meilisearch-http/tests/search.rs +++ b/meilisearch-http/tests/search.rs @@ -1,16 +1,13 @@ use std::convert::Into; - use serde_json::json; +use assert_json_diff::assert_json_eq; mod common; #[test] fn basic_search() { - let mut server = common::setup_server().unwrap(); - - common::enrich_server_with_movies_index(&mut server).unwrap(); - common::enrich_server_with_movies_settings(&mut server).unwrap(); - common::enrich_server_with_movies_documents(&mut server).unwrap(); + let mut server = common::Server::with_uid("movies"); + server.populate_movies(); // 1 - Simple search // q: Captain @@ -18,7 +15,7 @@ fn basic_search() { let query = "q=captain&limit=3"; - let json = json!([ + let expect = json!([ { "id": 299537, "popularity": 44.726, @@ -72,7 +69,8 @@ fn basic_search() { } ]); - common::search(&mut server, query, json); + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); // 2 - Simple search with offset // q: Captain @@ -81,7 +79,7 @@ fn basic_search() { let query = "q=captain&limit=3&offset=1"; - let json = json!([ + let expect = json!([ { "id": 271110, "popularity": 37.431, @@ -136,7 +134,8 @@ fn basic_search() { } ]); - common::search(&mut server, query, json); + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); // 3 - Simple search with attribute to highlight all // q: Captain @@ -145,7 +144,7 @@ fn basic_search() { let query = "q=captain&limit=1&attributesToHighlight=*"; - let json = json!([ + let expect = json!([ { "id": 299537, "popularity": 44.726, @@ -182,7 +181,8 @@ fn basic_search() { } ]); - common::search(&mut server, query, json); + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); // 4 - Simple search with attribute to highlight title // q: Captain @@ -191,7 +191,7 @@ fn basic_search() { let query = "q=captain&limit=1&attributesToHighlight=title"; - let json = json!([ + let expect = json!([ { "id": 299537, "popularity": 44.726, @@ -228,7 +228,8 @@ fn basic_search() { } ]); - common::search(&mut server, query, json); + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); // 1 - Simple search with attribute to highlight title and tagline // q: Captain @@ -237,7 +238,7 @@ fn basic_search() { let query = "q=captain&limit=1&attributesToHighlight=title,tagline"; - let json = json!([ + let expect = json!([ { "id": 299537, "popularity": 44.726, @@ -274,7 +275,8 @@ fn basic_search() { } ]); - common::search(&mut server, query, json); + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); // 1 - Simple search with attribute to highlight title and overview // q: Captain @@ -283,7 +285,7 @@ fn basic_search() { let query = "q=captain&limit=1&attributesToHighlight=title,overview"; - let json = json!([ + let expect = json!([ { "id": 299537, "popularity": 44.726, @@ -320,7 +322,8 @@ fn basic_search() { } ]); - common::search(&mut server, query, json); + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); // 1 - Simple search with matches // q: Captain @@ -329,7 +332,7 @@ fn basic_search() { let query = "q=captain&limit=1&matches=true"; - let json = json!([ + let expect = json!([ { "id": 299537, "popularity": 44.726, @@ -363,7 +366,8 @@ fn basic_search() { } ]); - common::search(&mut server, query, json); + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); // 1 - Simple search with crop // q: Captain @@ -373,7 +377,7 @@ fn basic_search() { let query = "q=captain&limit=1&attributesToCrop=overview&cropLength=20"; - let json = json!([ + let expect = json!([ { "id": 299537, "popularity": 44.726, @@ -410,7 +414,8 @@ fn basic_search() { } ]); - common::search(&mut server, query, json); + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); // 1 - Simple search with attributes to retrieve // q: Captain @@ -419,7 +424,7 @@ fn basic_search() { let query = "q=captain&limit=1&attributesToRetrieve=title,tagline,overview,poster_path"; - let json = json!([ + let expect = json!([ { "title": "Captain Marvel", "tagline": "Higher. Further. Faster.", @@ -428,7 +433,8 @@ fn basic_search() { } ]); - common::search(&mut server, query, json); + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); // 1 - Simple search with filter // q: Captain @@ -437,7 +443,7 @@ fn basic_search() { let query = "q=captain&limit=3&filters=director:Anthony%20Russo"; - let json = json!([ + let expect = json!([ { "id": 271110, "popularity": 37.431, @@ -491,7 +497,8 @@ fn basic_search() { } ]); - common::search(&mut server, query, json); + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); // 1 - Simple search with attributes to highlight and matches // q: Captain @@ -501,7 +508,7 @@ fn basic_search() { let query = "q=captain&limit=1&attributesToHighlight=title,overview&matches=true"; - let json = json!( [ + let expect = json!( [ { "id": 299537, "popularity": 44.726, @@ -552,7 +559,8 @@ fn basic_search() { } ]); - common::search(&mut server, query, json); + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); // 1 - Simple search with attributes to highlight and matches and crop // q: Captain @@ -564,7 +572,7 @@ fn basic_search() { let query = "q=captain&limit=1&attributesToCrop=overview&cropLength=20&attributesToHighlight=title,overview&matches=true"; - let json = json!([ + let expect = json!([ { "id": 299537, "popularity": 44.726, @@ -615,14 +623,14 @@ fn basic_search() { } ]); - common::search(&mut server, query, json); + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); } #[test] fn search_with_settings_basic() { - let mut server = common::setup_server().unwrap(); - common::enrich_server_with_movies_index(&mut server).unwrap(); - common::enrich_server_with_movies_documents(&mut server).unwrap(); + let mut server = common::Server::with_uid("movies"); + server.populate_movies(); let config = json!({ "rankingRules": [ @@ -665,10 +673,10 @@ fn search_with_settings_basic() { "acceptNewFields": false, }); - common::update_config(&mut server, config); + server.update_all_settings(config); let query = "q=the%20avangers&limit=3"; - let response = json!([ + let expect = json!([ { "id": 24428, "popularity": 44.506, @@ -722,13 +730,14 @@ fn search_with_settings_basic() { } ]); - common::search(&mut server, query, response); + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); } #[test] fn search_with_settings_stop_words() { - let mut server = common::setup_server().unwrap(); - common::enrich_server_with_movies_index(&mut server).unwrap(); + let mut server = common::Server::with_uid("movies"); + server.populate_movies(); let config = json!({ "rankingRules": [ @@ -771,11 +780,10 @@ fn search_with_settings_stop_words() { "acceptNewFields": false, }); - common::update_config(&mut server, config); - common::enrich_server_with_movies_documents(&mut server).unwrap(); + server.update_all_settings(config); let query = "q=the%20avangers&limit=3"; - let response = json!([ + let expect = json!([ { "id": 299536, "popularity": 65.013, @@ -829,13 +837,14 @@ fn search_with_settings_stop_words() { } ]); - common::search(&mut server, query, response); + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); } #[test] fn search_with_settings_synonyms() { - let mut server = common::setup_server().unwrap(); - common::enrich_server_with_movies_index(&mut server).unwrap(); + let mut server = common::Server::with_uid("movies"); + server.populate_movies(); let config = json!({ "rankingRules": [ @@ -883,11 +892,10 @@ fn search_with_settings_synonyms() { "acceptNewFields": false, }); - common::update_config(&mut server, config); - common::enrich_server_with_movies_documents(&mut server).unwrap(); + server.update_all_settings(config); let query = "q=avangers&limit=3"; - let response = json!([ + let expect = json!([ { "id": 299536, "popularity": 65.013, @@ -941,13 +949,14 @@ fn search_with_settings_synonyms() { } ]); - common::search(&mut server, query, response); + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); } #[test] fn search_with_settings_ranking_rules() { - let mut server = common::setup_server().unwrap(); - common::enrich_server_with_movies_index(&mut server).unwrap(); + let mut server = common::Server::with_uid("movies"); + server.populate_movies(); let config = json!({ "rankingRules": [ @@ -990,11 +999,10 @@ fn search_with_settings_ranking_rules() { "acceptNewFields": false, }); - common::update_config(&mut server, config); - common::enrich_server_with_movies_documents(&mut server).unwrap(); + server.update_all_settings(config); let query = "q=avangers&limit=3"; - let response = json!([ + let expect = json!([ { "id": 99861, "popularity": 33.938, @@ -1048,13 +1056,14 @@ fn search_with_settings_ranking_rules() { } ]); - common::search(&mut server, query, response); + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); } #[test] fn search_with_settings_searchable_attributes() { - let mut server = common::setup_server().unwrap(); - common::enrich_server_with_movies_index(&mut server).unwrap(); + let mut server = common::Server::with_uid("movies"); + server.populate_movies(); let config = json!({ "rankingRules": [ @@ -1096,11 +1105,10 @@ fn search_with_settings_searchable_attributes() { "acceptNewFields": false, }); - common::update_config(&mut server, config); - common::enrich_server_with_movies_documents(&mut server).unwrap(); + server.update_all_settings(config); let query = "q=avangers&limit=3"; - let response = json!([ + let expect = json!([ { "id": 299536, "popularity": 65.013, @@ -1154,13 +1162,14 @@ fn search_with_settings_searchable_attributes() { } ]); - common::search(&mut server, query, response); + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); } #[test] fn search_with_settings_displayed_attributes() { - let mut server = common::setup_server().unwrap(); - common::enrich_server_with_movies_index(&mut server).unwrap(); + let mut server = common::Server::with_uid("movies"); + server.populate_movies(); let config = json!({ "rankingRules": [ @@ -1197,11 +1206,10 @@ fn search_with_settings_displayed_attributes() { "acceptNewFields": false, }); - common::update_config(&mut server, config); - common::enrich_server_with_movies_documents(&mut server).unwrap(); + server.update_all_settings(config); let query = "q=avangers&limit=3"; - let response = json!([ + let expect = json!([ { "id": 299536, "title": "Avengers: Infinity War", @@ -1225,13 +1233,14 @@ fn search_with_settings_displayed_attributes() { } ]); - common::search(&mut server, query, response); + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); } #[test] fn search_with_settings_searchable_attributes_2() { - let mut server = common::setup_server().unwrap(); - common::enrich_server_with_movies_index(&mut server).unwrap(); + let mut server = common::Server::with_uid("movies"); + server.populate_movies(); let config = json!({ "rankingRules": [ @@ -1268,11 +1277,10 @@ fn search_with_settings_searchable_attributes_2() { "acceptNewFields": false, }); - common::update_config(&mut server, config); - common::enrich_server_with_movies_documents(&mut server).unwrap(); + server.update_all_settings(config); let query = "q=avangers&limit=3"; - let response = json!([ + let expect = json!([ { "id": 299536, "title": "Avengers: Infinity War", @@ -1296,5 +1304,6 @@ fn search_with_settings_searchable_attributes_2() { } ]); - common::search(&mut server, query, response); + let (response, _status_code) = server.search(query); + assert_json_eq!(expect, response["hits"].clone(), ordered: false); } diff --git a/meilisearch-http/tests/settings.rs b/meilisearch-http/tests/settings.rs index eedd8cb53..ecd5e107a 100644 --- a/meilisearch-http/tests/settings.rs +++ b/meilisearch-http/tests/settings.rs @@ -1,45 +1,17 @@ use std::convert::Into; -use std::time::Duration; - use assert_json_diff::assert_json_eq; -use async_std::io::prelude::*; -use async_std::task::{block_on, sleep}; -use http_service::Body; use serde_json::json; -use serde_json::Value; mod common; -// Process: -// - Write a full settings update -// - Delete all settings -// Check: -// - Settings are deleted, all fields are null -// - POST success repond Status Code 202 -// - Get success repond Status Code 200 -// - Delete success repond Status Code 202 #[test] fn write_all_and_delete() { - let mut server = common::setup_server().unwrap(); - - // 1 - Create the index - - let body = json!({ - "uid": "movies", - "identifier": "id", - }) - .to_string() - .into_bytes(); - - let req = http::Request::post("/indexes") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 201); + let mut server = common::Server::with_uid("movies"); + server.populate_movies(); // 2 - Send the settings - let json = json!({ + let body = json!({ "rankingRules": [ "typo", "words", @@ -79,53 +51,23 @@ fn write_all_and_delete() { "acceptNewFields": false, }); - let body = json.to_string().into_bytes(); - - let req = http::Request::post("/indexes/movies/settings") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 202); - - block_on(sleep(Duration::from_secs(1))); + server.update_all_settings(body.clone()); // 3 - Get all settings and compare to the previous one - let req = http::Request::get("/indexes/movies/settings") - .body(Body::empty()) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); + let (response, _status_code) = server.get_all_settings(); - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res_value: Value = serde_json::from_slice(&buf).unwrap(); - - assert_json_eq!(json, res_value, ordered: false); + assert_json_eq!(body, response, ordered: false); // 4 - Delete all settings - let req = http::Request::delete("/indexes/movies/settings") - .body(Body::empty()) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 202); + server.delete_all_settings(); - block_on(sleep(Duration::from_secs(2))); + // 5 - Get all settings and check if they are set to default values - // 5 - Get all settings and check if they are empty + let (response, _status_code) = server.get_all_settings(); - let req = http::Request::get("/indexes/movies/settings") - .body(Body::empty()) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res_value: Value = serde_json::from_slice(&buf).unwrap(); - - let json = json!({ + let expect = json!({ "rankingRules": [ "typo", "words", @@ -136,61 +78,61 @@ fn write_all_and_delete() { ], "distinctAttribute": null, "searchableAttributes": [ + "poster_path", + "director", "id", - "release_date", + "production_companies", + "producer", "poster", - "description", - "title", "movie_id", - "rank" + "vote_count", + "cast", + "release_date", + "vote_average", + "rank", + "genres", + "overview", + "description", + "tagline", + "popularity", + "title" ], "displayedAttributes": [ - "movie_id", - "description", + "poster_path", "poster", + "vote_count", "id", - "release_date", + "movie_id", + "title", "rank", - "title" + "tagline", + "cast", + "producer", + "production_companies", + "description", + "director", + "genres", + "release_date", + "overview", + "vote_average", + "popularity" ], "stopWords": null, "synonyms": null, "acceptNewFields": true, }); - assert_json_eq!(json, res_value, ordered: false); + assert_json_eq!(expect, response, ordered: false); } -// Process: -// - Write a full setting update -// - Rewrite an other settings confirmation -// Check: -// - Settings are overwrited -// - Forgotten attributes are deleted -// - Null attributes are deleted -// - Empty attribute are deleted #[test] fn write_all_and_update() { - let mut server = common::setup_server().unwrap(); - - // 1 - Create the index - - let body = json!({ - "uid": "movies", - "identifier": "id", - }) - .to_string() - .into_bytes(); - - let req = http::Request::post("/indexes") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 201); + let mut server = common::Server::with_uid("movies"); + server.populate_movies(); // 2 - Send the settings - let json = json!({ + let body = json!({ "rankingRules": [ "typo", "words", @@ -230,33 +172,17 @@ fn write_all_and_update() { "acceptNewFields": false, }); - let body = json.to_string().into_bytes(); - - let req = http::Request::post("/indexes/movies/settings") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 202); - - block_on(sleep(Duration::from_secs(1))); + server.update_all_settings(body.clone()); // 3 - Get all settings and compare to the previous one - let req = http::Request::get("/indexes/movies/settings") - .body(Body::empty()) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); + let (response, _status_code) = server.get_all_settings(); - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res_value: Value = serde_json::from_slice(&buf).unwrap(); - - assert_json_eq!(json, res_value, ordered: false); + assert_json_eq!(body, response, ordered: false); // 4 - Update all settings - let json_update = json!({ + let body = json!({ "rankingRules": [ "typo", "words", @@ -287,29 +213,13 @@ fn write_all_and_update() { "acceptNewFields": false, }); - let body_update = json_update.to_string().into_bytes(); - - let req = http::Request::post("/indexes/movies/settings") - .body(Body::from(body_update)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 202); - - block_on(sleep(Duration::from_secs(1))); + server.update_all_settings(body); // 5 - Get all settings and check if the content is the same of (4) - let req = http::Request::get("/indexes/movies/settings") - .body(Body::empty()) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); + let (response, _status_code) = server.get_all_settings(); - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res_value: Value = serde_json::from_slice(&buf).unwrap(); - - let res_expected = json!({ + let expected = json!({ "rankingRules": [ "typo", "words", @@ -340,5 +250,5 @@ fn write_all_and_update() { "acceptNewFields": false }); - assert_json_eq!(res_expected, res_value, ordered: false); + assert_json_eq!(expected, response, ordered: false); } diff --git a/meilisearch-http/tests/settings_ranking_rules.rs b/meilisearch-http/tests/settings_ranking_rules.rs index 66ee08393..39e4c7061 100644 --- a/meilisearch-http/tests/settings_ranking_rules.rs +++ b/meilisearch-http/tests/settings_ranking_rules.rs @@ -1,44 +1,16 @@ -use std::time::Duration; - use assert_json_diff::assert_json_eq; -use async_std::io::prelude::*; -use async_std::task::{block_on, sleep}; -use http_service::Body; use serde_json::json; -use serde_json::Value; mod common; -// Process: -// - Write a full settings update -// - Delete all settings -// Check: -// - Settings are deleted, all fields are null -// - POST success repond Status Code 202 -// - Get success repond Status Code 200 -// - Delete success repond Status Code 202 #[test] fn write_all_and_delete() { - let mut server = common::setup_server().unwrap(); - - // 1 - Create the index - - let body = json!({ - "uid": "movies", - "identifier": "uid", - }) - .to_string() - .into_bytes(); - - let req = http::Request::post("/indexes") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 201); + let mut server = common::Server::with_uid("movies"); + server.populate_movies(); // 2 - Send the settings - let json = json!([ + let body = json!([ "typo", "words", "proximity", @@ -49,51 +21,21 @@ fn write_all_and_delete() { "desc(rank)", ]); - let body = json.to_string().into_bytes(); - - let req = http::Request::post("/indexes/movies/settings/ranking-rules") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 202); - - block_on(sleep(Duration::from_secs(2))); + server.update_ranking_rules(body.clone()); // 3 - Get all settings and compare to the previous one - let req = http::Request::get("/indexes/movies/settings/ranking-rules") - .body(Body::empty()) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); + let (response, _status_code) = server.get_ranking_rules(); - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res_value: Value = serde_json::from_slice(&buf).unwrap(); - - assert_json_eq!(json, res_value, ordered: false); + assert_json_eq!(body, response, ordered: false); // 4 - Delete all settings - let req = http::Request::delete("/indexes/movies/settings/ranking-rules") - .body(Body::empty()) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 202); - - block_on(sleep(Duration::from_secs(2))); + server.delete_ranking_rules(); // 5 - Get all settings and check if they are empty - let req = http::Request::get("/indexes/movies/settings/ranking-rules") - .body(Body::empty()) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); - - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res_value: Value = serde_json::from_slice(&buf).unwrap(); + let (response, _status_code) = server.get_ranking_rules(); let json = json!([ "typo", @@ -104,39 +46,17 @@ fn write_all_and_delete() { "exactness" ]); - assert_json_eq!(json, res_value, ordered: false); + assert_json_eq!(expect, response, ordered: false); } -// Process: -// - Write a full setting update -// - Rewrite an other settings confirmation -// Check: -// - Settings are overwrited -// - Forgotten attributes are deleted -// - Null attributes are deleted -// - Empty attribute are deleted #[test] fn write_all_and_update() { - let mut server = common::setup_server().unwrap(); - - // 1 - Create the index - - let body = json!({ - "uid": "movies", - "identifier": "uid", - }) - .to_string() - .into_bytes(); - - let req = http::Request::post("/indexes") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 201); + let mut server = common::Server::with_uid("movies"); + server.populate_movies(); // 2 - Send the settings - let json = json!([ + let body = json!([ "typo", "words", "proximity", @@ -147,33 +67,17 @@ fn write_all_and_update() { "desc(rank)", ]); - let body = json.to_string().into_bytes(); - - let req = http::Request::post("/indexes/movies/settings/ranking-rules") - .body(Body::from(body)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 202); - - block_on(sleep(Duration::from_secs(1))); + server.update_ranking_rules(body.clone()); // 3 - Get all settings and compare to the previous one - let req = http::Request::get("/indexes/movies/settings/ranking-rules") - .body(Body::empty()) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); + let (response, _status_code) = server.get_ranking_rules(); - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res_value: Value = serde_json::from_slice(&buf).unwrap(); - - assert_json_eq!(json, res_value, ordered: false); + assert_json_eq!(body, response, ordered: false); // 4 - Update all settings - let json_update = json!([ + let body = json!([ "typo", "words", "proximity", @@ -183,29 +87,13 @@ fn write_all_and_update() { "desc(release_date)", ]); - let body_update = json_update.to_string().into_bytes(); - - let req = http::Request::post("/indexes/movies/settings/ranking-rules") - .body(Body::from(body_update)) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 202); - - block_on(sleep(Duration::from_secs(1))); + server.update_ranking_rules(body); // 5 - Get all settings and check if the content is the same of (4) - let req = http::Request::get("/indexes/movies/settings/ranking-rules") - .body(Body::empty()) - .unwrap(); - let res = server.simulate(req).unwrap(); - assert_eq!(res.status(), 200); + let (response, _status_code) = server.get_ranking_rules(); - let mut buf = Vec::new(); - block_on(res.into_body().read_to_end(&mut buf)).unwrap(); - let res_value: Value = serde_json::from_slice(&buf).unwrap(); - - let res_expected = json!([ + let expected = json!([ "typo", "words", "proximity", @@ -215,5 +103,5 @@ fn write_all_and_update() { "desc(release_date)", ]); - assert_json_eq!(res_expected, res_value, ordered: false); + assert_json_eq!(expected, response, ordered: false); } From 54c675e19586d16a98d5bbce74a8f1991b326be8 Mon Sep 17 00:00:00 2001 From: qdequele Date: Wed, 4 Mar 2020 15:06:16 +0100 Subject: [PATCH 05/11] fix delete-batch route; #493 --- meilisearch-http/src/routes/mod.rs | 2 +- meilisearch-http/tests/common.rs | 11 ++++---- meilisearch-http/tests/documents_delete.rs | 30 ++++++++++++++++++++++ 3 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 meilisearch-http/tests/documents_delete.rs diff --git a/meilisearch-http/src/routes/mod.rs b/meilisearch-http/src/routes/mod.rs index 0dde83595..6fa5ec1e6 100644 --- a/meilisearch-http/src/routes/mod.rs +++ b/meilisearch-http/src/routes/mod.rs @@ -65,7 +65,7 @@ pub fn load_routes(app: &mut tide::Server) { .get(|ctx| into_response(document::get_document(ctx))) .delete(|ctx| into_response(document::delete_document(ctx))); - app.at("/indexes/:index/documents/:identifier/delete-batch") + app.at("/indexes/:index/documents/delete-batch") .post(|ctx| into_response(document::delete_multiple_documents(ctx))); app.at("/indexes/:index/settings") diff --git a/meilisearch-http/tests/common.rs b/meilisearch-http/tests/common.rs index 190101479..3836d4d74 100644 --- a/meilisearch-http/tests/common.rs +++ b/meilisearch-http/tests/common.rs @@ -58,6 +58,7 @@ impl Server { let response: Value = serde_json::from_slice(&buf).unwrap(); if response["status"] == "processed" { + eprintln!("{:?}", response); return; } block_on(sleep(Duration::from_secs(1))); @@ -219,14 +220,14 @@ impl Server { self.delete_request_async(&url); } - pub fn get_document(&mut self, document_id: u64) -> (Value, StatusCode) { - let url = format!("/indexes/{}/documents/{}", self.uid, document_id); + pub fn get_document(&mut self, document_id: impl ToString) -> (Value, StatusCode) { + let url = format!("/indexes/{}/documents/{}", self.uid, document_id.to_string()); self.get_request(&url) } - pub fn delete_document(&mut self, document_id: u64) -> (Value, StatusCode) { - let url = format!("/indexes/{}/documents/{}", self.uid, document_id); - self.delete_request(&url) + pub fn delete_document(&mut self, document_id: impl ToString) -> (Value, StatusCode) { + let url = format!("/indexes/{}/documents/{}", self.uid, document_id.to_string()); + self.delete_request_async(&url) } pub fn delete_multiple_documents(&mut self, body: Value) { diff --git a/meilisearch-http/tests/documents_delete.rs b/meilisearch-http/tests/documents_delete.rs new file mode 100644 index 000000000..02017aaf1 --- /dev/null +++ b/meilisearch-http/tests/documents_delete.rs @@ -0,0 +1,30 @@ +mod common; + +#[test] +fn delete() { + let mut server = common::Server::with_uid("movies"); + server.populate_movies(); + + let (_response, status_code) = server.get_document(419704); + assert_eq!(status_code, 200); + + server.delete_document(419704); + + let (_response, status_code) = server.get_document(419704); + assert_eq!(status_code, 404); +} + +#[test] +fn delete_batch() { + let mut server = common::Server::with_uid("movies"); + server.populate_movies(); + + let (_response, status_code) = server.get_document(419704); + assert_eq!(status_code, 200); + + let body = serde_json::json!([419704,512200,181812]); + server.delete_multiple_documents(body); + + let (_response, status_code) = server.get_document(419704); + assert_eq!(status_code, 404); +} From 041eed2a06a4bd422876b000c0059822e558d83c Mon Sep 17 00:00:00 2001 From: qdequele Date: Wed, 4 Mar 2020 15:58:36 +0100 Subject: [PATCH 06/11] no id returned; fix #492 --- meilisearch-http/tests/index.rs | 31 +++++++++++++++++++++++++++++++ meilisearch-schema/src/schema.rs | 14 +++++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/meilisearch-http/tests/index.rs b/meilisearch-http/tests/index.rs index 3215cc4b0..b637134a7 100644 --- a/meilisearch-http/tests/index.rs +++ b/meilisearch-http/tests/index.rs @@ -1,4 +1,5 @@ use serde_json::json; +use assert_json_diff::assert_json_eq; mod common; @@ -467,3 +468,33 @@ fn create_index_failed() { assert_eq!(res_value.as_object().unwrap().len(), 1); assert_eq!(message, "invalid data"); } + + +#[test] +fn create_index_with_identifier() { + let mut server = common::Server::with_uid("movies"); + + let body = json!({ + "uid": "movies", + "identifier": "id", + }); + + let (_response, status_code) = server.create_index(body); + assert_eq!(status_code, 201); + + let body = json!([{ + "id": 123, + "text": "The mask" + }]); + + server.add_or_replace_multiple_documents(body.clone()); + + let (response, _status_code) = server.get_document(123); + + let expect = json!({ + "id": 123, + "text": "The mask" + }); + + assert_json_eq!(response, expect, ordered: false); +} diff --git a/meilisearch-schema/src/schema.rs b/meilisearch-schema/src/schema.rs index 4283f203d..2f9eee4f5 100644 --- a/meilisearch-schema/src/schema.rs +++ b/meilisearch-schema/src/schema.rs @@ -21,13 +21,21 @@ impl Schema { let mut fields_map = FieldsMap::default(); let field_id = fields_map.insert(name).unwrap(); + let mut displayed = HashSet::new(); + let mut indexed = Vec::new(); + let mut indexed_map = HashMap::new(); + + displayed.insert(field_id); + indexed.push(field_id); + indexed_map.insert(field_id, 0.into()); + Schema { fields_map, identifier: field_id, ranked: HashSet::new(), - displayed: HashSet::new(), - indexed: Vec::new(), - indexed_map: HashMap::new(), + displayed, + indexed, + indexed_map, accept_new_fields: true, } } From c5b6e641a45f79d82c463654e18d06f51cf08d7c Mon Sep 17 00:00:00 2001 From: qdequele Date: Thu, 5 Mar 2020 11:44:30 +0100 Subject: [PATCH 07/11] index UID format; fix #497 --- meilisearch-http/src/error.rs | 5 ++ meilisearch-http/src/routes/index.rs | 8 +++- meilisearch-http/tests/documents_delete.rs | 2 + meilisearch-http/tests/index.rs | 54 +++++++++++++++++++++- 4 files changed, 67 insertions(+), 2 deletions(-) diff --git a/meilisearch-http/src/error.rs b/meilisearch-http/src/error.rs index a2b539687..9c1a91a4e 100644 --- a/meilisearch-http/src/error.rs +++ b/meilisearch-http/src/error.rs @@ -22,6 +22,7 @@ pub enum ResponseError { BadParameter(String, String), OpenIndex(String), CreateIndex(String), + InvalidIndexUid, Maintenance, } @@ -108,6 +109,10 @@ impl IntoResponse for ResponseError { format!("Impossible to open index; {}", err), StatusCode::BAD_REQUEST, ), + ResponseError::InvalidIndexUid => error( + "Index must have a valid uid; Index uid can be of type integer or string only composed of alphanumeric characters, hyphens (-) and underscores (_).".to_string(), + StatusCode::BAD_REQUEST, + ), ResponseError::Maintenance => error( String::from("Server is in maintenance, please try again later"), StatusCode::SERVICE_UNAVAILABLE, diff --git a/meilisearch-http/src/routes/index.rs b/meilisearch-http/src/routes/index.rs index 6625d24c3..b8adbb531 100644 --- a/meilisearch-http/src/routes/index.rs +++ b/meilisearch-http/src/routes/index.rs @@ -138,7 +138,13 @@ pub async fn create_index(mut ctx: Request) -> SResult { let db = &ctx.state().db; let uid = match body.uid { - Some(uid) => uid, + Some(uid) => { + if uid.chars().all(|x| x.is_ascii_alphanumeric() || x == '-' || x == '_') { + uid + } else { + return Err(ResponseError::InvalidIndexUid) + } + }, None => loop { let uid = generate_uid(); if db.open_index(&uid).is_none() { diff --git a/meilisearch-http/tests/documents_delete.rs b/meilisearch-http/tests/documents_delete.rs index 02017aaf1..35041e023 100644 --- a/meilisearch-http/tests/documents_delete.rs +++ b/meilisearch-http/tests/documents_delete.rs @@ -14,6 +14,8 @@ fn delete() { assert_eq!(status_code, 404); } + +// Resolve teh issue https://github.com/meilisearch/MeiliSearch/issues/493 #[test] fn delete_batch() { let mut server = common::Server::with_uid("movies"); diff --git a/meilisearch-http/tests/index.rs b/meilisearch-http/tests/index.rs index b637134a7..4bb173e5e 100644 --- a/meilisearch-http/tests/index.rs +++ b/meilisearch-http/tests/index.rs @@ -470,8 +470,10 @@ fn create_index_failed() { } + +// Resolve issue https://github.com/meilisearch/MeiliSearch/issues/492 #[test] -fn create_index_with_identifier() { +fn create_index_with_identifier_and_index() { let mut server = common::Server::with_uid("movies"); let body = json!({ @@ -498,3 +500,53 @@ fn create_index_with_identifier() { assert_json_eq!(response, expect, ordered: false); } + +// Resolve issue https://github.com/meilisearch/MeiliSearch/issues/497 +#[test] +fn create_index_with_invalid_uid() { + let mut server = common::Server::with_uid(""); + + let body = json!({ + "uid": "the movies" + }); + + let (response, status_code) = server.create_index(body); + assert_eq!(status_code, 400); + + let message = response["message"].as_str().unwrap(); + assert_eq!(response.as_object().unwrap().len(), 1); + assert_eq!(message, "Index must have a valid uid; Index uid can be of type integer or string only composed of alphanumeric characters, hyphens (-) and underscores (_)."); + + let body = json!({ + "uid": "%$#" + }); + + let (response, status_code) = server.create_index(body); + assert_eq!(status_code, 400); + + let message = response["message"].as_str().unwrap(); + assert_eq!(response.as_object().unwrap().len(), 1); + assert_eq!(message, "Index must have a valid uid; Index uid can be of type integer or string only composed of alphanumeric characters, hyphens (-) and underscores (_)."); + + let body = json!({ + "uid": "the~movies" + }); + + let (response, status_code) = server.create_index(body); + assert_eq!(status_code, 400); + + let message = response["message"].as_str().unwrap(); + assert_eq!(response.as_object().unwrap().len(), 1); + assert_eq!(message, "Index must have a valid uid; Index uid can be of type integer or string only composed of alphanumeric characters, hyphens (-) and underscores (_)."); + + let body = json!({ + "uid": "🎉" + }); + + let (response, status_code) = server.create_index(body); + assert_eq!(status_code, 400); + + let message = response["message"].as_str().unwrap(); + assert_eq!(response.as_object().unwrap().len(), 1); + assert_eq!(message, "Index must have a valid uid; Index uid can be of type integer or string only composed of alphanumeric characters, hyphens (-) and underscores (_)."); +} From d56968cb234cc234eb8a80fb56e3cfe19f4bc381 Mon Sep 17 00:00:00 2001 From: qdequele Date: Thu, 5 Mar 2020 14:17:15 +0100 Subject: [PATCH 08/11] default values of synonyms and stop-words; fix #499 fix #504 --- meilisearch-http/src/routes/mod.rs | 2 +- meilisearch-http/src/routes/setting.rs | 18 +------- meilisearch-http/tests/settings_stop_words.rs | 41 +++++++++++++++++++ 3 files changed, 44 insertions(+), 17 deletions(-) create mode 100644 meilisearch-http/tests/settings_stop_words.rs diff --git a/meilisearch-http/src/routes/mod.rs b/meilisearch-http/src/routes/mod.rs index 6fa5ec1e6..31be1cacf 100644 --- a/meilisearch-http/src/routes/mod.rs +++ b/meilisearch-http/src/routes/mod.rs @@ -105,7 +105,7 @@ pub fn load_routes(app: &mut tide::Server) { .post(|ctx| into_response(synonym::update(ctx))) .delete(|ctx| into_response(synonym::delete(ctx))); - app.at("/indexes/:index/settings/stop_words") + app.at("/indexes/:index/settings/stop-words") .get(|ctx| into_response(stop_words::get(ctx))) .post(|ctx| into_response(stop_words::update(ctx))) .delete(|ctx| into_response(stop_words::delete(ctx))); diff --git a/meilisearch-http/src/routes/setting.rs b/meilisearch-http/src/routes/setting.rs index 19f26ec4c..81cd12a72 100644 --- a/meilisearch-http/src/routes/setting.rs +++ b/meilisearch-http/src/routes/setting.rs @@ -18,34 +18,20 @@ pub async fn get_all(ctx: Request) -> SResult { let stop_words_fst = index.main.stop_words_fst(&reader)?; let stop_words = stop_words_fst.unwrap_or_default().stream().into_strs()?; let stop_words: BTreeSet = stop_words.into_iter().collect(); - let stop_words = if !stop_words.is_empty() { - Some(stop_words) - } else { - None - }; let synonyms_fst = index.main.synonyms_fst(&reader)?.unwrap_or_default(); let synonyms_list = synonyms_fst.stream().into_strs()?; let mut synonyms = BTreeMap::new(); - let index_synonyms = &index.synonyms; - for synonym in synonyms_list { let alternative_list = index_synonyms.synonyms(&reader, synonym.as_bytes())?; - if let Some(list) = alternative_list { let list = list.stream().into_strs()?; synonyms.insert(synonym, list); } } - let synonyms = if !synonyms.is_empty() { - Some(synonyms) - } else { - None - }; - let ranking_rules = index .main .ranking_rules(&reader)? @@ -90,8 +76,8 @@ pub async fn get_all(ctx: Request) -> SResult { distinct_attribute: Some(distinct_attribute), searchable_attributes, displayed_attributes, - stop_words: Some(stop_words), - synonyms: Some(synonyms), + stop_words: Some(Some(stop_words)), + synonyms: Some(Some(synonyms)), accept_new_fields: Some(accept_new_fields), }; diff --git a/meilisearch-http/tests/settings_stop_words.rs b/meilisearch-http/tests/settings_stop_words.rs new file mode 100644 index 000000000..195a2d69e --- /dev/null +++ b/meilisearch-http/tests/settings_stop_words.rs @@ -0,0 +1,41 @@ +use assert_json_diff::assert_json_eq; +use serde_json::json; + +mod common; + +#[test] +fn update_stop_words() { + let mut server = common::Server::with_uid("movies"); + let body = json!({ + "uid": "movies", + "identifier": "id", + }); + server.create_index(body); + + // 1 - Get stop words + + let (response, _status_code) = server.get_stop_words(); + assert_eq!(response.as_array().unwrap().is_empty(), true); + + // 2 - Update stop words + + let body = json!([ + "the", + "a" + ]); + server.update_stop_words(body.clone()); + + // 3 - Get all stop words and compare to the previous one + + let (response, _status_code) = server.get_stop_words(); + assert_json_eq!(body, response, ordered: false); + + // 4 - Delete all stop words + + server.delete_stop_words(); + + // 5 - Get all stop words and check if they are empty + + let (response, _status_code) = server.get_stop_words(); + assert_eq!(response.as_array().unwrap().is_empty(), true); +} From f4ae0844ab3f00120e4ca2476a22409495e67571 Mon Sep 17 00:00:00 2001 From: qdequele Date: Thu, 5 Mar 2020 15:05:04 +0100 Subject: [PATCH 09/11] replace index-new-field route to accept-new-fields; fix #503 --- Cargo.lock | 2 +- meilisearch-http/src/routes/mod.rs | 2 +- meilisearch-http/tests/common.rs | 2 +- meilisearch-http/tests/settings.rs | 6 +- .../tests/settings_accept_new_fields.rs | 290 ++++++++++++++++++ 5 files changed, 296 insertions(+), 6 deletions(-) create mode 100644 meilisearch-http/tests/settings_accept_new_fields.rs diff --git a/Cargo.lock b/Cargo.lock index aa6f99b8a..d985635be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -37,7 +37,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "assert-json-diff" version = "1.0.1" -source = "git+https://github.com/qdequele/assert-json-diff#29bdf99315e510abb2824ccb9353b3a7a330cbc4" +source = "git+https://github.com/qdequele/assert-json-diff#9012a0c8866d0f2db0ef9a6242e4a19d1e8c67e4" dependencies = [ "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/meilisearch-http/src/routes/mod.rs b/meilisearch-http/src/routes/mod.rs index 31be1cacf..93b7e1391 100644 --- a/meilisearch-http/src/routes/mod.rs +++ b/meilisearch-http/src/routes/mod.rs @@ -96,7 +96,7 @@ pub fn load_routes(app: &mut tide::Server) { .post(|ctx| into_response(setting::update_displayed(ctx))) .delete(|ctx| into_response(setting::delete_displayed(ctx))); - app.at("/indexes/:index/settings/index-new-field") + app.at("/indexes/:index/settings/accept-new-fields") .get(|ctx| into_response(setting::get_accept_new_fields(ctx))) .post(|ctx| into_response(setting::update_accept_new_fields(ctx))); diff --git a/meilisearch-http/tests/common.rs b/meilisearch-http/tests/common.rs index 3836d4d74..7acb1c8a2 100644 --- a/meilisearch-http/tests/common.rs +++ b/meilisearch-http/tests/common.rs @@ -58,7 +58,7 @@ impl Server { let response: Value = serde_json::from_slice(&buf).unwrap(); if response["status"] == "processed" { - eprintln!("{:?}", response); + eprintln!("{:#?}", response); return; } block_on(sleep(Duration::from_secs(1))); diff --git a/meilisearch-http/tests/settings.rs b/meilisearch-http/tests/settings.rs index ecd5e107a..2f9c7c43c 100644 --- a/meilisearch-http/tests/settings.rs +++ b/meilisearch-http/tests/settings.rs @@ -117,8 +117,8 @@ fn write_all_and_delete() { "vote_average", "popularity" ], - "stopWords": null, - "synonyms": null, + "stopWords": [], + "synonyms": {}, "acceptNewFields": true, }); @@ -242,7 +242,7 @@ fn write_all_and_update() { "rank", "poster", ], - "stopWords": null, + "stopWords": [], "synonyms": { "wolverine": ["xmen", "logan"], "logan": ["wolverine", "xmen"], diff --git a/meilisearch-http/tests/settings_accept_new_fields.rs b/meilisearch-http/tests/settings_accept_new_fields.rs new file mode 100644 index 000000000..6157e7cb5 --- /dev/null +++ b/meilisearch-http/tests/settings_accept_new_fields.rs @@ -0,0 +1,290 @@ +use assert_json_diff::assert_json_eq; +use serde_json::json; + +mod common; + +#[test] +fn index_new_fields_default() { + let mut server = common::Server::with_uid("movies"); + let body = json!({ + "uid": "movies", + "identifier": "id", + }); + server.create_index(body); + + // 1 - Add a document + + let body = json!([{ + "id": 1, + "title": "I'm a legend", + }]); + + server.add_or_replace_multiple_documents(body); + + // 2 - Get the complete document + + let expected = json!({ + "id": 1, + "title": "I'm a legend", + }); + + let (response, status_code) = server.get_document(1); + assert_eq!(status_code, 200); + assert_json_eq!(response, expected); + + // 3 - Add a document with more fields + + let body = json!([{ + "id": 2, + "title": "I'm not a legend", + "description": "A bad copy of the original movie I'm a lengend" + }]); + + server.add_or_replace_multiple_documents(body); + + // 4 - Get the complete document + + let expected = json!({ + "id": 2, + "title": "I'm not a legend", + "description": "A bad copy of the original movie I'm a lengend" + }); + + let (response, status_code) = server.get_document(2); + assert_eq!(status_code, 200); + assert_json_eq!(response, expected); +} + +#[test] +fn index_new_fields_true() { + let mut server = common::Server::with_uid("movies"); + let body = json!({ + "uid": "movies", + "identifier": "id", + }); + server.create_index(body); + + // 1 - Set indexNewFields = true + + server.update_accept_new_fields(json!(true)); + + // 2 - Add a document + + let body = json!([{ + "id": 1, + "title": "I'm a legend", + }]); + + server.add_or_replace_multiple_documents(body); + + // 3 - Get the complete document + + let expected = json!({ + "id": 1, + "title": "I'm a legend", + }); + + let (response, status_code) = server.get_document(1); + assert_eq!(status_code, 200); + assert_json_eq!(response, expected); + + // 4 - Add a document with more fields + + let body = json!([{ + "id": 2, + "title": "I'm not a legend", + "description": "A bad copy of the original movie I'm a lengend" + }]); + + server.add_or_replace_multiple_documents(body); + + // 5 - Get the complete document + + let expected = json!({ + "id": 2, + "title": "I'm not a legend", + "description": "A bad copy of the original movie I'm a lengend" + }); + + let (response, status_code) = server.get_document(2); + assert_eq!(status_code, 200); + assert_json_eq!(response, expected); +} + +#[test] +fn index_new_fields_false() { + let mut server = common::Server::with_uid("movies"); + let body = json!({ + "uid": "movies", + "identifier": "id", + }); + server.create_index(body); + + // 1 - Set indexNewFields = false + + server.update_accept_new_fields(json!(false)); + + // 2 - Add a document + + let body = json!([{ + "id": 1, + "title": "I'm a legend", + }]); + + server.add_or_replace_multiple_documents(body); + + // 3 - Get the complete document + + let expected = json!({ + "id": 1, + }); + + let (response, status_code) = server.get_document(1); + assert_eq!(status_code, 200); + assert_json_eq!(response, expected); + + // 4 - Add a document with more fields + + let body = json!([{ + "id": 2, + "title": "I'm not a legend", + "description": "A bad copy of the original movie I'm a lengend" + }]); + + server.add_or_replace_multiple_documents(body); + + // 5 - Get the complete document + + let expected = json!({ + "id": 2, + }); + + let (response, status_code) = server.get_document(2); + assert_eq!(status_code, 200); + assert_json_eq!(response, expected); +} + +#[test] +fn index_new_fields_true_then_false() { + let mut server = common::Server::with_uid("movies"); + let body = json!({ + "uid": "movies", + "identifier": "id", + }); + server.create_index(body); + + // 1 - Set indexNewFields = true + + server.update_accept_new_fields(json!(true)); + + // 2 - Add a document + + let body = json!([{ + "id": 1, + "title": "I'm a legend", + }]); + + server.add_or_replace_multiple_documents(body); + + // 3 - Get the complete document + + let expected = json!({ + "id": 1, + "title": "I'm a legend", + }); + + let (response, status_code) = server.get_document(1); + assert_eq!(status_code, 200); + assert_json_eq!(response, expected); + + // 4 - Set indexNewFields = false + + server.update_accept_new_fields(json!(false)); + + // 5 - Add a document with more fields + + let body = json!([{ + "id": 2, + "title": "I'm not a legend", + "description": "A bad copy of the original movie I'm a lengend" + }]); + + server.add_or_replace_multiple_documents(body); + + // 6 - Get the complete document + + let expected = json!({ + "id": 2, + "title": "I'm not a legend", + }); + + let (response, status_code) = server.get_document(2); + assert_eq!(status_code, 200); + assert_json_eq!(response, expected); +} + +#[test] +fn index_new_fields_false_then_true() { + let mut server = common::Server::with_uid("movies"); + let body = json!({ + "uid": "movies", + "identifier": "id", + }); + server.create_index(body); + + // 1 - Set indexNewFields = false + + server.update_accept_new_fields(json!(false)); + + // 2 - Add a document + + let body = json!([{ + "id": 1, + "title": "I'm a legend", + }]); + + server.add_or_replace_multiple_documents(body); + + // 3 - Get the complete document + + let expected = json!({ + "id": 1, + }); + + let (response, status_code) = server.get_document(1); + assert_eq!(status_code, 200); + assert_json_eq!(response, expected); + + // 4 - Set indexNewFields = false + + server.update_accept_new_fields(json!(true)); + + // 5 - Add a document with more fields + + let body = json!([{ + "id": 2, + "title": "I'm not a legend", + "description": "A bad copy of the original movie I'm a lengend" + }]); + + server.add_or_replace_multiple_documents(body); + + // 6 - Get the complete document + + let expected = json!({ + "id": 1, + }); + + let (response, status_code) = server.get_document(1); + assert_eq!(status_code, 200); + assert_json_eq!(response, expected); + + let expected = json!({ + "id": 2, + "description": "A bad copy of the original movie I'm a lengend" + }); + + let (response, status_code) = server.get_document(2); + assert_eq!(status_code, 200); + assert_json_eq!(response, expected); +} From 8aeddec9827febd51e08cccb05406d587ce00876 Mon Sep 17 00:00:00 2001 From: qdequele Date: Thu, 5 Mar 2020 15:06:18 +0100 Subject: [PATCH 10/11] remove the route to get identifier on settings; fix #502 --- meilisearch-http/src/routes/mod.rs | 3 --- meilisearch-http/src/routes/setting.rs | 13 ------------- 2 files changed, 16 deletions(-) diff --git a/meilisearch-http/src/routes/mod.rs b/meilisearch-http/src/routes/mod.rs index 93b7e1391..e6b914437 100644 --- a/meilisearch-http/src/routes/mod.rs +++ b/meilisearch-http/src/routes/mod.rs @@ -83,9 +83,6 @@ pub fn load_routes(app: &mut tide::Server) { .post(|ctx| into_response(setting::update_distinct(ctx))) .delete(|ctx| into_response(setting::delete_distinct(ctx))); - app.at("/indexes/:index/settings/identifier") - .get(|ctx| into_response(setting::get_identifier(ctx))); - app.at("/indexes/:index/settings/searchable-attributes") .get(|ctx| into_response(setting::get_searchable(ctx))) .post(|ctx| into_response(setting::update_searchable(ctx))) diff --git a/meilisearch-http/src/routes/setting.rs b/meilisearch-http/src/routes/setting.rs index 81cd12a72..3402cac1e 100644 --- a/meilisearch-http/src/routes/setting.rs +++ b/meilisearch-http/src/routes/setting.rs @@ -255,19 +255,6 @@ pub async fn delete_distinct(ctx: Request) -> SResult { Ok(tide::Response::new(202).body_json(&response_body)?) } -pub async fn get_identifier(ctx: Request) -> SResult { - ctx.is_allowed(Private)?; - let index = ctx.index()?; - let db = &ctx.state().db; - let reader = db.main_read_txn()?; - - let schema = index.main.schema(&reader)?; - - let identifier = schema.map(|s| s.identifier().to_string()); - - Ok(tide::Response::new(200).body_json(&identifier).unwrap()) -} - pub async fn get_searchable(ctx: Request) -> SResult { ctx.is_allowed(Private)?; let index = ctx.index()?; From 8df6d6e954854805c2a13a0ebe85971d16ecaf66 Mon Sep 17 00:00:00 2001 From: qdequele Date: Thu, 5 Mar 2020 15:18:19 +0100 Subject: [PATCH 11/11] fix error 500 when sending bad rankingRules; fix #500 --- meilisearch-http/src/routes/setting.rs | 18 ++++++--- meilisearch-http/tests/common.rs | 5 +++ .../tests/settings_ranking_rules.rs | 38 ++++++++++++++++++- 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/meilisearch-http/src/routes/setting.rs b/meilisearch-http/src/routes/setting.rs index 3402cac1e..ecb97f233 100644 --- a/meilisearch-http/src/routes/setting.rs +++ b/meilisearch-http/src/routes/setting.rs @@ -115,7 +115,8 @@ pub async fn update_all(mut ctx: Request) -> SResult { }; let mut writer = db.update_write_txn()?; - let update_id = index.settings_update(&mut writer, settings.into_update()?)?; + let settings = settings.into_update().map_err(ResponseError::bad_request)?; + let update_id = index.settings_update(&mut writer, settings)?; writer.commit()?; let response_body = IndexUpdateResponse { update_id }; @@ -177,7 +178,8 @@ pub async fn update_rules(mut ctx: Request) -> SResult { }; let mut writer = db.update_write_txn()?; - let update_id = index.settings_update(&mut writer, settings.into_update()?)?; + let settings = settings.into_update().map_err(ResponseError::bad_request)?; + let update_id = index.settings_update(&mut writer, settings)?; writer.commit()?; let response_body = IndexUpdateResponse { update_id }; @@ -229,7 +231,8 @@ pub async fn update_distinct(mut ctx: Request) -> SResult { }; let mut writer = db.update_write_txn()?; - let update_id = index.settings_update(&mut writer, settings.into_update()?)?; + let settings = settings.into_update().map_err(ResponseError::bad_request)?; + let update_id = index.settings_update(&mut writer, settings)?; writer.commit()?; let response_body = IndexUpdateResponse { update_id }; @@ -284,7 +287,8 @@ pub async fn update_searchable(mut ctx: Request) -> SResult { }; let mut writer = db.update_write_txn()?; - let update_id = index.settings_update(&mut writer, settings.into_update()?)?; + let settings = settings.into_update().map_err(ResponseError::bad_request)?; + let update_id = index.settings_update(&mut writer, settings)?; writer.commit()?; let response_body = IndexUpdateResponse { update_id }; @@ -342,7 +346,8 @@ pub async fn update_displayed(mut ctx: Request) -> SResult { }; let mut writer = db.update_write_txn()?; - let update_id = index.settings_update(&mut writer, settings.into_update()?)?; + let settings = settings.into_update().map_err(ResponseError::bad_request)?; + let update_id = index.settings_update(&mut writer, settings)?; writer.commit()?; let response_body = IndexUpdateResponse { update_id }; @@ -395,7 +400,8 @@ pub async fn update_accept_new_fields(mut ctx: Request) -> SResult (Value, StatusCode) { + let url = format!("/indexes/{}/settings/ranking-rules", self.uid); + self.post_request(&url, body) + } + pub fn delete_ranking_rules(&mut self) -> (Value, StatusCode) { let url = format!("/indexes/{}/settings/ranking-rules", self.uid); self.delete_request_async(&url) diff --git a/meilisearch-http/tests/settings_ranking_rules.rs b/meilisearch-http/tests/settings_ranking_rules.rs index 39e4c7061..908dd9c31 100644 --- a/meilisearch-http/tests/settings_ranking_rules.rs +++ b/meilisearch-http/tests/settings_ranking_rules.rs @@ -37,7 +37,7 @@ fn write_all_and_delete() { let (response, _status_code) = server.get_ranking_rules(); - let json = json!([ + let expected = json!([ "typo", "words", "proximity", @@ -46,7 +46,7 @@ fn write_all_and_delete() { "exactness" ]); - assert_json_eq!(expect, response, ordered: false); + assert_json_eq!(expected, response, ordered: false); } #[test] @@ -105,3 +105,37 @@ fn write_all_and_update() { assert_json_eq!(expected, response, ordered: false); } + +#[test] +fn send_undefined_rule() { + let mut server = common::Server::with_uid("movies"); + let body = json!({ + "uid": "movies", + "identifier": "id", + }); + server.create_index(body); + + let body = json!([ + "typos", + ]); + + let (_response, status_code) = server.update_ranking_rules_sync(body); + assert_eq!(status_code, 400); +} + +#[test] +fn send_malformed_custom_rule() { + let mut server = common::Server::with_uid("movies"); + let body = json!({ + "uid": "movies", + "identifier": "id", + }); + server.create_index(body); + + let body = json!([ + "dsc(truc)", + ]); + + let (_response, status_code) = server.update_ranking_rules_sync(body); + assert_eq!(status_code, 400); +}