use assert_json_diff::assert_json_eq; use serde_json::json; use serde_json::Value; mod common; #[actix_rt::test] async fn create_index_with_name() { let mut server = common::Server::with_uid("movies"); // 1 - Create a new index let body = json!({ "name": "movies", }); let (res1_value, status_code) = server.create_index(body).await; 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(); let r1_created_at = res1_value["createdAt"].as_str().unwrap(); let r1_updated_at = res1_value["updatedAt"].as_str().unwrap(); assert_eq!(r1_name, "movies"); assert_eq!(r1_uid.len(), 8); assert!(r1_created_at.len() > 1); assert!(r1_updated_at.len() > 1); // 2 - Check the list of indexes let (res2_value, status_code) = server.list_indexes().await; 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(); let r2_uid = res2_value[0]["uid"].as_str().unwrap(); let r2_created_at = res2_value[0]["createdAt"].as_str().unwrap(); let r2_updated_at = res2_value[0]["updatedAt"].as_str().unwrap(); assert_eq!(r2_name, r1_name); assert_eq!(r2_uid.len(), r1_uid.len()); assert_eq!(r2_created_at.len(), r1_created_at.len()); assert_eq!(r2_updated_at.len(), r1_updated_at.len()); } #[actix_rt::test] async fn create_index_with_uid() { let mut server = common::Server::with_uid("movies"); // 1 - Create a new index let body = json!({ "uid": "movies", }); let (res1_value, status_code) = server.create_index(body.clone()).await; 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(); let r1_created_at = res1_value["createdAt"].as_str().unwrap(); let r1_updated_at = res1_value["updatedAt"].as_str().unwrap(); assert_eq!(r1_name, "movies"); assert_eq!(r1_uid, "movies"); assert!(r1_created_at.len() > 1); assert!(r1_updated_at.len() > 1); // 1.5 verify that error is thrown when trying to create the same index let (response, status_code) = server.create_index(body).await; assert_eq!(status_code, 400); assert_eq!(response["errorCode"].as_str().unwrap(), "index_already_exists"); // 2 - Check the list of indexes let (res2_value, status_code) = server.list_indexes().await; 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(); let r2_uid = res2_value[0]["uid"].as_str().unwrap(); let r2_created_at = res2_value[0]["createdAt"].as_str().unwrap(); let r2_updated_at = res2_value[0]["updatedAt"].as_str().unwrap(); assert_eq!(r2_name, r1_name); assert_eq!(r2_uid, r1_uid); assert_eq!(r2_created_at.len(), r1_created_at.len()); assert_eq!(r2_updated_at.len(), r1_updated_at.len()); } #[actix_rt::test] async fn create_index_with_name_and_uid() { let mut server = common::Server::with_uid("movies"); // 1 - Create a new index let body = json!({ "name": "Films", "uid": "fr_movies", }); let (res1_value, status_code) = server.create_index(body).await; 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(); let r1_created_at = res1_value["createdAt"].as_str().unwrap(); let r1_updated_at = res1_value["updatedAt"].as_str().unwrap(); assert_eq!(r1_name, "Films"); assert_eq!(r1_uid, "fr_movies"); assert!(r1_created_at.len() > 1); assert!(r1_updated_at.len() > 1); // 2 - Check the list of indexes let (res2_value, status_code) = server.list_indexes().await; 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(); let r2_uid = res2_value[0]["uid"].as_str().unwrap(); let r2_created_at = res2_value[0]["createdAt"].as_str().unwrap(); let r2_updated_at = res2_value[0]["updatedAt"].as_str().unwrap(); assert_eq!(r2_name, r1_name); assert_eq!(r2_uid, r1_uid); assert_eq!(r2_created_at.len(), r1_created_at.len()); assert_eq!(r2_updated_at.len(), r1_updated_at.len()); } #[actix_rt::test] async fn rename_index() { let mut server = common::Server::with_uid("movies"); // 1 - Create a new index let body = json!({ "name": "movies", "uid": "movies", }); let (res1_value, status_code) = server.create_index(body).await; 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(); let r1_created_at = res1_value["createdAt"].as_str().unwrap(); let r1_updated_at = res1_value["updatedAt"].as_str().unwrap(); assert_eq!(r1_name, "movies"); assert_eq!(r1_uid.len(), 6); assert!(r1_created_at.len() > 1); assert!(r1_updated_at.len() > 1); // 2 - Update an index name let body = json!({ "name": "TV Shows", }); let (res2_value, status_code) = server.update_index(body).await; assert_eq!(status_code, 200); assert_eq!(res2_value.as_object().unwrap().len(), 5); let r2_name = res2_value["name"].as_str().unwrap(); let r2_uid = res2_value["uid"].as_str().unwrap(); let r2_created_at = res2_value["createdAt"].as_str().unwrap(); let r2_updated_at = res2_value["updatedAt"].as_str().unwrap(); assert_eq!(r2_name, "TV Shows"); assert_eq!(r2_uid, r1_uid); assert_eq!(r2_created_at, r1_created_at); assert!(r2_updated_at.len() > 1); // 3 - Check the list of indexes let (res3_value, status_code) = server.list_indexes().await; assert_eq!(status_code, 200); assert_eq!(res3_value.as_array().unwrap().len(), 1); assert_eq!(res3_value[0].as_object().unwrap().len(), 5); let r3_name = res3_value[0]["name"].as_str().unwrap(); let r3_uid = res3_value[0]["uid"].as_str().unwrap(); let r3_created_at = res3_value[0]["createdAt"].as_str().unwrap(); let r3_updated_at = res3_value[0]["updatedAt"].as_str().unwrap(); assert_eq!(r3_name, r2_name); assert_eq!(r3_uid.len(), r1_uid.len()); assert_eq!(r3_created_at.len(), r1_created_at.len()); assert_eq!(r3_updated_at.len(), r2_updated_at.len()); } #[actix_rt::test] async fn delete_index_and_recreate_it() { let mut server = common::Server::with_uid("movies"); // 0 - delete unexisting index is error let (response, status_code) = server.delete_request("/indexes/test").await; assert_eq!(status_code, 404); assert_eq!(&response["errorCode"], "index_not_found"); // 1 - Create a new index let body = json!({ "name": "movies", "uid": "movies", }); let (res1_value, status_code) = server.create_index(body).await; 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(); let r1_created_at = res1_value["createdAt"].as_str().unwrap(); let r1_updated_at = res1_value["updatedAt"].as_str().unwrap(); assert_eq!(r1_name, "movies"); assert_eq!(r1_uid.len(), 6); assert!(r1_created_at.len() > 1); assert!(r1_updated_at.len() > 1); // 2 - Check the list of indexes let (res2_value, status_code) = server.list_indexes().await; 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(); let r2_uid = res2_value[0]["uid"].as_str().unwrap(); let r2_created_at = res2_value[0]["createdAt"].as_str().unwrap(); let r2_updated_at = res2_value[0]["updatedAt"].as_str().unwrap(); assert_eq!(r2_name, r1_name); assert_eq!(r2_uid.len(), r1_uid.len()); assert_eq!(r2_created_at.len(), r1_created_at.len()); assert_eq!(r2_updated_at.len(), r1_updated_at.len()); // 3- Delete an index let (_res2_value, status_code) = server.delete_index().await; assert_eq!(status_code, 204); // 4 - Check the list of indexes let (res2_value, status_code) = server.list_indexes().await; assert_eq!(status_code, 200); assert_eq!(res2_value.as_array().unwrap().len(), 0); // 5 - Create a new index let body = json!({ "name": "movies", }); let (res1_value, status_code) = server.create_index(body).await; 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(); let r1_created_at = res1_value["createdAt"].as_str().unwrap(); let r1_updated_at = res1_value["updatedAt"].as_str().unwrap(); assert_eq!(r1_name, "movies"); assert_eq!(r1_uid.len(), 8); assert!(r1_created_at.len() > 1); assert!(r1_updated_at.len() > 1); // 6 - Check the list of indexes let (res2_value, status_code) = server.list_indexes().await; 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(); let r2_uid = res2_value[0]["uid"].as_str().unwrap(); let r2_created_at = res2_value[0]["createdAt"].as_str().unwrap(); let r2_updated_at = res2_value[0]["updatedAt"].as_str().unwrap(); assert_eq!(r2_name, r1_name); assert_eq!(r2_uid.len(), r1_uid.len()); assert_eq!(r2_created_at.len(), r1_created_at.len()); assert_eq!(r2_updated_at.len(), r1_updated_at.len()); } #[actix_rt::test] async fn check_multiples_indexes() { let mut server = common::Server::with_uid("movies"); // 1 - Create a new index let body = json!({ "name": "movies", }); let (res1_value, status_code) = server.create_index(body).await; 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(); let r1_created_at = res1_value["createdAt"].as_str().unwrap(); let r1_updated_at = res1_value["updatedAt"].as_str().unwrap(); assert_eq!(r1_name, "movies"); assert_eq!(r1_uid.len(), 8); assert!(r1_created_at.len() > 1); assert!(r1_updated_at.len() > 1); // 2 - Check the list of indexes let (res2_value, status_code) = server.list_indexes().await; 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_0_name = res2_value[0]["name"].as_str().unwrap(); let r2_0_uid = res2_value[0]["uid"].as_str().unwrap(); let r2_0_created_at = res2_value[0]["createdAt"].as_str().unwrap(); let r2_0_updated_at = res2_value[0]["updatedAt"].as_str().unwrap(); assert_eq!(r2_0_name, r1_name); assert_eq!(r2_0_uid.len(), r1_uid.len()); assert_eq!(r2_0_created_at.len(), r1_created_at.len()); assert_eq!(r2_0_updated_at.len(), r1_updated_at.len()); // 3 - Create a new index let body = json!({ "name": "films", }); let (res3_value, status_code) = server.create_index(body).await; assert_eq!(status_code, 201); assert_eq!(res3_value.as_object().unwrap().len(), 5); let r3_name = res3_value["name"].as_str().unwrap(); let r3_uid = res3_value["uid"].as_str().unwrap(); let r3_created_at = res3_value["createdAt"].as_str().unwrap(); let r3_updated_at = res3_value["updatedAt"].as_str().unwrap(); assert_eq!(r3_name, "films"); assert_eq!(r3_uid.len(), 8); assert!(r3_created_at.len() > 1); assert!(r3_updated_at.len() > 1); // 4 - Check the list of indexes let (res4_value, status_code) = server.list_indexes().await; assert_eq!(status_code, 200); assert_eq!(res4_value.as_array().unwrap().len(), 2); assert_eq!(res4_value[0].as_object().unwrap().len(), 5); let r4_0_name = res4_value[0]["name"].as_str().unwrap(); let r4_0_uid = res4_value[0]["uid"].as_str().unwrap(); let r4_0_created_at = res4_value[0]["createdAt"].as_str().unwrap(); let r4_0_updated_at = res4_value[0]["updatedAt"].as_str().unwrap(); assert_eq!(res4_value[1].as_object().unwrap().len(), 5); let r4_1_name = res4_value[1]["name"].as_str().unwrap(); let r4_1_uid = res4_value[1]["uid"].as_str().unwrap(); let r4_1_created_at = res4_value[1]["createdAt"].as_str().unwrap(); let r4_1_updated_at = res4_value[1]["updatedAt"].as_str().unwrap(); if r4_0_name == r1_name { assert_eq!(r4_0_name, r1_name); assert_eq!(r4_0_uid.len(), r1_uid.len()); assert_eq!(r4_0_created_at.len(), r1_created_at.len()); assert_eq!(r4_0_updated_at.len(), r1_updated_at.len()); } else { assert_eq!(r4_0_name, r3_name); assert_eq!(r4_0_uid.len(), r3_uid.len()); assert_eq!(r4_0_created_at.len(), r3_created_at.len()); assert_eq!(r4_0_updated_at.len(), r3_updated_at.len()); } if r4_1_name == r1_name { assert_eq!(r4_1_name, r1_name); assert_eq!(r4_1_uid.len(), r1_uid.len()); assert_eq!(r4_1_created_at.len(), r1_created_at.len()); assert_eq!(r4_1_updated_at.len(), r1_updated_at.len()); } else { assert_eq!(r4_1_name, r3_name); assert_eq!(r4_1_uid.len(), r3_uid.len()); assert_eq!(r4_1_created_at.len(), r3_created_at.len()); assert_eq!(r4_1_updated_at.len(), r3_updated_at.len()); } } #[actix_rt::test] async fn create_index_failed() { let mut server = common::Server::with_uid("movies"); // 2 - Push index creation with empty json body let body = json!({}); let (res_value, status_code) = server.create_index(body).await; assert_eq!(status_code, 400); let message = res_value["message"].as_str().unwrap(); assert_eq!(res_value.as_object().unwrap().len(), 4); assert_eq!(message, "Index creation must have an uid"); // 3 - Create a index with extra data let body = json!({ "name": "movies", "active": true }); let (_res_value, status_code) = server.create_index(body).await; assert_eq!(status_code, 400); // 3 - Create a index with wrong data type let body = json!({ "name": "movies", "uid": 0 }); let (_res_value, status_code) = server.create_index(body).await; assert_eq!(status_code, 400); } // Resolve issue https://github.com/meilisearch/MeiliSearch/issues/492 #[actix_rt::test] async fn create_index_with_primary_key_and_index() { let mut server = common::Server::with_uid("movies"); // 1 - Create the index let body = json!({ "uid": "movies", "primaryKey": "id", }); let (_response, status_code) = server.create_index(body).await; assert_eq!(status_code, 201); // 2 - Add content let body = json!([{ "id": 123, "text": "The mask" }]); server.add_or_replace_multiple_documents(body.clone()).await; // 3 - Retreive document let (response, _status_code) = server.get_document(123).await; 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 when the given index uid is not valid // Should have a 400 status code // Should have the right error message #[actix_rt::test] async fn create_index_with_invalid_uid() { let mut server = common::Server::with_uid(""); // 1 - Create the index with invalid uid let body = json!({ "uid": "the movies" }); let (response, status_code) = server.create_index(body).await; assert_eq!(status_code, 400); let message = response["message"].as_str().unwrap(); assert_eq!(response.as_object().unwrap().len(), 4); 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 (_)."); // 2 - Create the index with invalid uid let body = json!({ "uid": "%$#" }); let (response, status_code) = server.create_index(body).await; assert_eq!(status_code, 400); let message = response["message"].as_str().unwrap(); assert_eq!(response.as_object().unwrap().len(), 4); 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 (_)."); // 3 - Create the index with invalid uid let body = json!({ "uid": "the~movies" }); let (response, status_code) = server.create_index(body).await; assert_eq!(status_code, 400); let message = response["message"].as_str().unwrap(); assert_eq!(response.as_object().unwrap().len(), 4); 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 (_)."); // 4 - Create the index with invalid uid let body = json!({ "uid": "🎉" }); let (response, status_code) = server.create_index(body).await; assert_eq!(status_code, 400); let message = response["message"].as_str().unwrap(); assert_eq!(response.as_object().unwrap().len(), 4); 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 (_)."); } // Test that it's possible to add primary_key if it's not already set on index creation #[actix_rt::test] async fn create_index_and_add_indentifier_after() { let mut server = common::Server::with_uid("movies"); // 1 - Create the index with no primary_key let body = json!({ "uid": "movies", }); let (response, status_code) = server.create_index(body).await; assert_eq!(status_code, 201); assert_eq!(response["primaryKey"], json!(null)); // 2 - Update the index and add an primary_key. let body = json!({ "primaryKey": "id", }); let (response, status_code) = server.update_index(body).await; assert_eq!(status_code, 200); eprintln!("response: {:#?}", response); assert_eq!(response["primaryKey"].as_str().unwrap(), "id"); // 3 - Get index to verify if the primary_key is good let (response, status_code) = server.get_index().await; assert_eq!(status_code, 200); assert_eq!(response["primaryKey"].as_str().unwrap(), "id"); } // Test that it's impossible to change the primary_key #[actix_rt::test] async fn create_index_and_update_indentifier_after() { let mut server = common::Server::with_uid("movies"); // 1 - Create the index with no primary_key let body = json!({ "uid": "movies", "primaryKey": "id", }); let (response, status_code) = server.create_index(body).await; assert_eq!(status_code, 201); assert_eq!(response["primaryKey"].as_str().unwrap(), "id"); // 2 - Update the index and add an primary_key. let body = json!({ "primaryKey": "skuid", }); let (_response, status_code) = server.update_index(body).await; assert_eq!(status_code, 400); // 3 - Get index to verify if the primary_key still the first one let (response, status_code) = server.get_index().await; assert_eq!(status_code, 200); assert_eq!(response["primaryKey"].as_str().unwrap(), "id"); } // Test that schema inference work well #[actix_rt::test] async fn create_index_without_primary_key_and_add_document() { let mut server = common::Server::with_uid("movies"); // 1 - Create the index with no primary_key let body = json!({ "uid": "movies", }); let (response, status_code) = server.create_index(body).await; assert_eq!(status_code, 201); assert_eq!(response["primaryKey"], json!(null)); // 2 - Add a document let body = json!([{ "id": 123, "title": "I'm a legend", }]); server.add_or_update_multiple_documents(body).await; // 3 - Get index to verify if the primary_key is good let (response, status_code) = server.get_index().await; assert_eq!(status_code, 200); assert_eq!(response["primaryKey"].as_str().unwrap(), "id"); } // Test search with no primary_key #[actix_rt::test] async fn create_index_without_primary_key_and_search() { let mut server = common::Server::with_uid("movies"); // 1 - Create the index with no primary_key let body = json!({ "uid": "movies", }); let (response, status_code) = server.create_index(body).await; assert_eq!(status_code, 201); assert_eq!(response["primaryKey"], json!(null)); // 2 - Search let query = "q=captain&limit=3"; let (response, status_code) = server.search_get(&query).await; assert_eq!(status_code, 200); assert_eq!(response["hits"].as_array().unwrap().len(), 0); } // Test the error message when we push an document update and impossibility to find primary key // Test issue https://github.com/meilisearch/MeiliSearch/issues/517 #[actix_rt::test] async fn check_add_documents_without_primary_key() { let mut server = common::Server::with_uid("movies"); // 1 - Create the index with no primary_key let body = json!({ "uid": "movies", }); let (response, status_code) = server.create_index(body).await; assert_eq!(status_code, 201); assert_eq!(response["primaryKey"], json!(null)); // 2- Add document let body = json!([{ "title": "Test", "comment": "comment test" }]); let (response, status_code) = server.add_or_replace_multiple_documents_sync(body).await; assert_eq!(response.as_object().unwrap().len(), 4); assert_eq!(response["errorCode"], "missing_primary_key"); assert_eq!(status_code, 400); } #[actix_rt::test] async fn check_first_update_should_bring_up_processed_status_after_first_docs_addition() { let mut server = common::Server::with_uid("test"); let body = json!({ "uid": "test", }); // 1. Create Index let (response, status_code) = server.create_index(body).await; assert_eq!(status_code, 201); assert_eq!(response["primaryKey"], json!(null)); let dataset = include_bytes!("assets/test_set.json"); let body: Value = serde_json::from_slice(dataset).unwrap(); // 2. Index the documents from movies.json, present inside of assets directory server.add_or_replace_multiple_documents(body).await; // 3. Fetch the status of the indexing done above. let (response, status_code) = server.get_all_updates_status().await; // 4. Verify the fetch is successful and indexing status is 'processed' assert_eq!(status_code, 200); assert_eq!(response[0]["status"], "processed"); }