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-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<regex::Regex> = 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/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/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/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<String>,
 
     /// 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,
 
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<Data>) -> SResult<Response> {
     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/src/routes/mod.rs b/meilisearch-http/src/routes/mod.rs
index e9188100a..e6b914437 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<Data>) {
         .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")
@@ -83,9 +83,6 @@ pub fn load_routes(app: &mut tide::Server<Data>) {
         .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)))
@@ -96,7 +93,7 @@ pub fn load_routes(app: &mut tide::Server<Data>) {
         .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)));
 
@@ -105,7 +102,7 @@ pub fn load_routes(app: &mut tide::Server<Data>) {
         .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)));
@@ -113,7 +110,7 @@ pub fn load_routes(app: &mut tide::Server<Data>) {
     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)))
diff --git a/meilisearch-http/src/routes/setting.rs b/meilisearch-http/src/routes/setting.rs
index 19f26ec4c..ecb97f233 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<Data>) -> SResult<Response> {
     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<String> = 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<Data>) -> SResult<Response> {
         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),
     };
 
@@ -129,7 +115,8 @@ pub async fn update_all(mut ctx: Request<Data>) -> SResult<Response> {
     };
 
     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 };
@@ -191,7 +178,8 @@ pub async fn update_rules(mut ctx: Request<Data>) -> SResult<Response> {
     };
 
     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 };
@@ -243,7 +231,8 @@ pub async fn update_distinct(mut ctx: Request<Data>) -> SResult<Response> {
     };
 
     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 };
@@ -269,19 +258,6 @@ pub async fn delete_distinct(ctx: Request<Data>) -> SResult<Response> {
     Ok(tide::Response::new(202).body_json(&response_body)?)
 }
 
-pub async fn get_identifier(ctx: Request<Data>) -> SResult<Response> {
-    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<Data>) -> SResult<Response> {
     ctx.is_allowed(Private)?;
     let index = ctx.index()?;
@@ -311,7 +287,8 @@ pub async fn update_searchable(mut ctx: Request<Data>) -> SResult<Response> {
     };
 
     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 };
@@ -369,7 +346,8 @@ pub async fn update_displayed(mut ctx: Request<Data>) -> SResult<Response> {
     };
 
     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 };
@@ -422,7 +400,8 @@ pub async fn update_accept_new_fields(mut ctx: Request<Data>) -> SResult<Respons
     };
 
     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 };
diff --git a/meilisearch-http/tests/common.rs b/meilisearch-http/tests/common.rs
index 605caa833..95e59a1d3 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,433 @@ use serde_json::json;
 use tempdir::TempDir;
 use tide::server::Service;
 
-pub fn setup_server() -> Result<TestBackend<Service<Data>>, Box<dyn Error>> {
-    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<Service<Data>>,
 }
 
-pub fn enrich_server_with_movies_index(
-    server: &mut TestBackend<Service<Data>>,
-) -> Result<(), Box<dyn Error>> {
-    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<Service<Data>>,
-) -> Result<(), Box<dyn Error>> {
-    let json = json!({
-        "rankingRules": [
-            "typo",
-            "words",
-            "proximity",
-            "attribute",
-            "wordsPosition",
-            "dsc(popularity)",
-            "exactness",
-            "dsc(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" {
+                eprintln!("{:#?}", response);
+                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<Service<Data>>,
-) -> Result<(), Box<dyn Error>> {
-    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<Service<Data>>, 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<Service<Data>>, 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<Service<Data>>, 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: 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: 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) {
+        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 update_ranking_rules_sync(&mut self, body: Value) -> (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)
+    }
+
+    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/documents_delete.rs b/meilisearch-http/tests/documents_delete.rs
new file mode 100644
index 000000000..35041e023
--- /dev/null
+++ b/meilisearch-http/tests/documents_delete.rs
@@ -0,0 +1,32 @@
+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);
+}
+
+
+// Resolve teh issue https://github.com/meilisearch/MeiliSearch/issues/493
+#[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);
+}
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..4bb173e5e 100644
--- a/meilisearch-http/tests/index.rs
+++ b/meilisearch-http/tests/index.rs
@@ -1,14 +1,11 @@
-use async_std::io::prelude::*;
-use async_std::task::block_on;
-use http_service::Body;
 use serde_json::json;
-use serde_json::Value;
+use assert_json_diff::assert_json_eq;
 
 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 +13,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 +32,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 +49,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 +57,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 +76,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 +93,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 +102,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 +121,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 +139,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 +159,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 +169,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 +189,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 +207,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 +215,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 +228,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 +236,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 +255,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 +273,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 +293,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 +311,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 +319,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 +339,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 +360,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 +380,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 +424,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 +444,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,21 +459,94 @@ 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);
     assert_eq!(message, "invalid data");
 }
+
+
+
+// Resolve issue https://github.com/meilisearch/MeiliSearch/issues/492
+#[test]
+fn create_index_with_identifier_and_index() {
+    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);
+}
+
+// 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 (_).");
+}
diff --git a/meilisearch-http/tests/search.rs b/meilisearch-http/tests/search.rs
index b03ff4a0d..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": [
@@ -631,9 +639,9 @@ fn search_with_settings_basic() {
         "proximity",
         "attribute",
         "wordsPosition",
-        "dsc(popularity)",
+        "desc(popularity)",
         "exactness",
-        "dsc(vote_average)"
+        "desc(vote_average)"
       ],
       "distinctAttribute": null,
       "identifier": "id",
@@ -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": [
@@ -737,9 +746,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",
@@ -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": [
@@ -844,9 +853,9 @@ fn search_with_settings_synonyms() {
         "proximity",
         "attribute",
         "wordsPosition",
-        "dsc(popularity)",
+        "desc(popularity)",
         "exactness",
-        "dsc(vote_average)"
+        "desc(vote_average)"
       ],
       "distinctAttribute": null,
       "identifier": "id",
@@ -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": [
@@ -958,7 +967,7 @@ fn search_with_settings_ranking_rules() {
         "wordsPosition",
         "asc(vote_average)",
         "exactness",
-        "dsc(popularity)"
+        "desc(popularity)"
       ],
       "distinctAttribute": null,
       "identifier": "id",
@@ -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": [
@@ -1063,9 +1072,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",
@@ -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": [
@@ -1169,9 +1178,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",
@@ -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": [
@@ -1240,9 +1249,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",
@@ -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 09a8c96bd..2f9c7c43c 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",
@@ -47,8 +19,8 @@ fn write_all_and_delete() {
             "attribute",
             "wordsPosition",
             "exactness",
-            "dsc(release_date)",
-            "dsc(rank)",
+            "desc(release_date)",
+            "desc(rank)",
         ],
         "distinctAttribute": "movie_id",
         "searchableAttributes": [
@@ -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"
-        ],
-        "displayedAttributes": [
-          "movie_id",
-          "description",
-          "poster",
-          "id",
+          "vote_count",
+          "cast",
           "release_date",
+          "vote_average",
           "rank",
+          "genres",
+          "overview",
+          "description",
+          "tagline",
+          "popularity",
           "title"
         ],
-        "stopWords": null,
-        "synonyms": null,
+        "displayedAttributes": [
+          "poster_path",
+          "poster",
+          "vote_count",
+          "id",
+          "movie_id",
+          "title",
+          "rank",
+          "tagline",
+          "cast",
+          "producer",
+          "production_companies",
+          "description",
+          "director",
+          "genres",
+          "release_date",
+          "overview",
+          "vote_average",
+          "popularity"
+        ],
+        "stopWords": [],
+        "synonyms": {},
         "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",
@@ -198,8 +140,8 @@ fn write_all_and_update() {
             "attribute",
             "wordsPosition",
             "exactness",
-            "dsc(release_date)",
-            "dsc(rank)",
+            "desc(release_date)",
+            "desc(rank)",
         ],
         "distinctAttribute": "movie_id",
         "searchableAttributes": [
@@ -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",
@@ -264,7 +190,7 @@ fn write_all_and_update() {
             "attribute",
             "wordsPosition",
             "exactness",
-            "dsc(release_date)",
+            "desc(release_date)",
         ],
         "searchableAttributes": [
             "title",
@@ -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",
@@ -317,7 +227,7 @@ fn write_all_and_update() {
             "attribute",
             "wordsPosition",
             "exactness",
-            "dsc(release_date)",
+            "desc(release_date)",
         ],
         "distinctAttribute": null,
         "searchableAttributes": [
@@ -332,7 +242,7 @@ fn write_all_and_update() {
             "rank",
             "poster",
         ],
-        "stopWords": null,
+        "stopWords": [],
         "synonyms": {
             "wolverine": ["xmen", "logan"],
             "logan": ["wolverine", "xmen"],
@@ -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_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);
+}
diff --git a/meilisearch-http/tests/settings_ranking_rules.rs b/meilisearch-http/tests/settings_ranking_rules.rs
index 786f72dd5..908dd9c31 100644
--- a/meilisearch-http/tests/settings_ranking_rules.rs
+++ b/meilisearch-http/tests/settings_ranking_rules.rs
@@ -1,101 +1,43 @@
-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",
         "attribute",
         "wordsPosition",
         "exactness",
-        "dsc(release_date)",
-        "dsc(rank)",
+        "desc(release_date)",
+        "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 (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 json = json!([
+    let expected = json!([
         "typo",
         "words",
         "proximity",
@@ -104,116 +46,96 @@ fn write_all_and_delete() {
         "exactness"
     ]);
 
-    assert_json_eq!(json, res_value, ordered: false);
+    assert_json_eq!(expected, 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",
         "attribute",
         "wordsPosition",
         "exactness",
-        "dsc(release_date)",
-        "dsc(rank)",
+        "desc(release_date)",
+        "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",
         "attribute",
         "wordsPosition",
         "exactness",
-        "dsc(release_date)",
+        "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",
         "attribute",
         "wordsPosition",
         "exactness",
-        "dsc(release_date)",
+        "desc(release_date)",
     ]);
 
-    assert_json_eq!(res_expected, res_value, ordered: false);
+    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);
 }
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);
+}
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,
         }
     }