mirror of
https://github.com/meilisearch/MeiliSearch
synced 2024-11-12 16:08:55 +01:00
a30e02c18c
implements: https://github.com/meilisearch/specifications/blob/develop/text/0060-refashion-updates-apis.md linked PR: - #1889 - #1891 - #1892 - #1902 - #1906 - #1911 - #1914 - #1915 - #1916 - #1918 - #1924 - #1925 - #1926 - #1930 - #1936 - #1937 - #1942 - #1944 - #1945 - #1946 - #1947 - #1950 - #1951 - #1957 - #1959 - #1960 - #1961 - #1962 - #1964 - https://github.com/meilisearch/milli/pull/414 - https://github.com/meilisearch/milli/pull/409 - https://github.com/meilisearch/milli/pull/406 - https://github.com/meilisearch/milli/pull/418 - close #1687 - close #1786 - close #1940 - close #1948 - close #1949 - close #1932 - close #1956
452 lines
14 KiB
Rust
452 lines
14 KiB
Rust
use crate::common::Server;
|
|
use serde_json::json;
|
|
|
|
use super::DOCUMENTS;
|
|
|
|
#[actix_rt::test]
|
|
async fn search_unexisting_index() {
|
|
let server = Server::new().await;
|
|
let index = server.index("test");
|
|
|
|
let expected_response = json!({
|
|
"message": "Index `test` not found.",
|
|
"code": "index_not_found",
|
|
"type": "invalid_request",
|
|
"link": "https://docs.meilisearch.com/errors#index_not_found"
|
|
});
|
|
|
|
index
|
|
.search(json!({"q": "hello"}), |response, code| {
|
|
assert_eq!(code, 404);
|
|
assert_eq!(response, expected_response);
|
|
})
|
|
.await;
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn search_unexisting_parameter() {
|
|
let server = Server::new().await;
|
|
let index = server.index("test");
|
|
|
|
index
|
|
.search(json!({"marin": "hello"}), |response, code| {
|
|
assert_eq!(code, 400, "{}", response);
|
|
assert_eq!(response["code"], "bad_request");
|
|
})
|
|
.await;
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn filter_invalid_syntax_object() {
|
|
let server = Server::new().await;
|
|
let index = server.index("test");
|
|
|
|
index
|
|
.update_settings(json!({"filterableAttributes": ["title"]}))
|
|
.await;
|
|
|
|
let documents = DOCUMENTS.clone();
|
|
index.add_documents(documents, None).await;
|
|
index.wait_task(1).await;
|
|
|
|
let expected_response = json!({
|
|
"message": "Was expecting an operation `=`, `!=`, `>=`, `>`, `<=`, `<`, `TO` or `_geoRadius` at `title & Glass`.\n1:14 title & Glass",
|
|
"code": "invalid_filter",
|
|
"type": "invalid_request",
|
|
"link": "https://docs.meilisearch.com/errors#invalid_filter"
|
|
});
|
|
index
|
|
.search(json!({"filter": "title & Glass"}), |response, code| {
|
|
assert_eq!(response, expected_response);
|
|
assert_eq!(code, 400);
|
|
})
|
|
.await;
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn filter_invalid_syntax_array() {
|
|
let server = Server::new().await;
|
|
let index = server.index("test");
|
|
|
|
index
|
|
.update_settings(json!({"filterableAttributes": ["title"]}))
|
|
.await;
|
|
|
|
let documents = DOCUMENTS.clone();
|
|
index.add_documents(documents, None).await;
|
|
index.wait_task(1).await;
|
|
|
|
let expected_response = json!({
|
|
"message": "Was expecting an operation `=`, `!=`, `>=`, `>`, `<=`, `<`, `TO` or `_geoRadius` at `title & Glass`.\n1:14 title & Glass",
|
|
"code": "invalid_filter",
|
|
"type": "invalid_request",
|
|
"link": "https://docs.meilisearch.com/errors#invalid_filter"
|
|
});
|
|
index
|
|
.search(json!({"filter": [["title & Glass"]]}), |response, code| {
|
|
assert_eq!(response, expected_response);
|
|
assert_eq!(code, 400);
|
|
})
|
|
.await;
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn filter_invalid_syntax_string() {
|
|
let server = Server::new().await;
|
|
let index = server.index("test");
|
|
|
|
index
|
|
.update_settings(json!({"filterableAttributes": ["title"]}))
|
|
.await;
|
|
|
|
let documents = DOCUMENTS.clone();
|
|
index.add_documents(documents, None).await;
|
|
index.wait_task(1).await;
|
|
|
|
let expected_response = json!({
|
|
"message": "Found unexpected characters at the end of the filter: `XOR title = Glass`. You probably forgot an `OR` or an `AND` rule.\n15:32 title = Glass XOR title = Glass",
|
|
"code": "invalid_filter",
|
|
"type": "invalid_request",
|
|
"link": "https://docs.meilisearch.com/errors#invalid_filter"
|
|
});
|
|
index
|
|
.search(
|
|
json!({"filter": "title = Glass XOR title = Glass"}),
|
|
|response, code| {
|
|
assert_eq!(response, expected_response);
|
|
assert_eq!(code, 400);
|
|
},
|
|
)
|
|
.await;
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn filter_invalid_attribute_array() {
|
|
let server = Server::new().await;
|
|
let index = server.index("test");
|
|
|
|
index
|
|
.update_settings(json!({"filterableAttributes": ["title"]}))
|
|
.await;
|
|
|
|
let documents = DOCUMENTS.clone();
|
|
index.add_documents(documents, None).await;
|
|
index.wait_task(1).await;
|
|
|
|
let expected_response = json!({
|
|
"message": "Attribute `many` is not filterable. Available filterable attributes are: `title`.\n1:5 many = Glass",
|
|
"code": "invalid_filter",
|
|
"type": "invalid_request",
|
|
"link": "https://docs.meilisearch.com/errors#invalid_filter"
|
|
});
|
|
index
|
|
.search(json!({"filter": [["many = Glass"]]}), |response, code| {
|
|
assert_eq!(response, expected_response);
|
|
assert_eq!(code, 400);
|
|
})
|
|
.await;
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn filter_invalid_attribute_string() {
|
|
let server = Server::new().await;
|
|
let index = server.index("test");
|
|
|
|
index
|
|
.update_settings(json!({"filterableAttributes": ["title"]}))
|
|
.await;
|
|
|
|
let documents = DOCUMENTS.clone();
|
|
index.add_documents(documents, None).await;
|
|
index.wait_task(1).await;
|
|
|
|
let expected_response = json!({
|
|
"message": "Attribute `many` is not filterable. Available filterable attributes are: `title`.\n1:5 many = Glass",
|
|
"code": "invalid_filter",
|
|
"type": "invalid_request",
|
|
"link": "https://docs.meilisearch.com/errors#invalid_filter"
|
|
});
|
|
index
|
|
.search(json!({"filter": "many = Glass"}), |response, code| {
|
|
assert_eq!(response, expected_response);
|
|
assert_eq!(code, 400);
|
|
})
|
|
.await;
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn filter_reserved_geo_attribute_array() {
|
|
let server = Server::new().await;
|
|
let index = server.index("test");
|
|
|
|
index
|
|
.update_settings(json!({"filterableAttributes": ["title"]}))
|
|
.await;
|
|
|
|
let documents = DOCUMENTS.clone();
|
|
index.add_documents(documents, None).await;
|
|
index.wait_task(1).await;
|
|
|
|
let expected_response = json!({
|
|
"message": "`_geo` is a reserved keyword and thus can't be used as a filter expression. Use the _geoRadius(latitude, longitude, distance) built-in rule to filter on _geo field coordinates.\n1:5 _geo = Glass",
|
|
"code": "invalid_filter",
|
|
"type": "invalid_request",
|
|
"link": "https://docs.meilisearch.com/errors#invalid_filter"
|
|
});
|
|
index
|
|
.search(json!({"filter": [["_geo = Glass"]]}), |response, code| {
|
|
assert_eq!(response, expected_response);
|
|
assert_eq!(code, 400);
|
|
})
|
|
.await;
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn filter_reserved_geo_attribute_string() {
|
|
let server = Server::new().await;
|
|
let index = server.index("test");
|
|
|
|
index
|
|
.update_settings(json!({"filterableAttributes": ["title"]}))
|
|
.await;
|
|
|
|
let documents = DOCUMENTS.clone();
|
|
index.add_documents(documents, None).await;
|
|
index.wait_task(1).await;
|
|
|
|
let expected_response = json!({
|
|
"message": "`_geo` is a reserved keyword and thus can't be used as a filter expression. Use the _geoRadius(latitude, longitude, distance) built-in rule to filter on _geo field coordinates.\n1:5 _geo = Glass",
|
|
"code": "invalid_filter",
|
|
"type": "invalid_request",
|
|
"link": "https://docs.meilisearch.com/errors#invalid_filter"
|
|
});
|
|
index
|
|
.search(json!({"filter": "_geo = Glass"}), |response, code| {
|
|
assert_eq!(response, expected_response);
|
|
assert_eq!(code, 400);
|
|
})
|
|
.await;
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn filter_reserved_attribute_array() {
|
|
let server = Server::new().await;
|
|
let index = server.index("test");
|
|
|
|
index
|
|
.update_settings(json!({"filterableAttributes": ["title"]}))
|
|
.await;
|
|
|
|
let documents = DOCUMENTS.clone();
|
|
index.add_documents(documents, None).await;
|
|
index.wait_task(1).await;
|
|
|
|
let expected_response = json!({
|
|
"message": "`_geoDistance` is a reserved keyword and thus can't be used as a filter expression.\n1:13 _geoDistance = Glass",
|
|
"code": "invalid_filter",
|
|
"type": "invalid_request",
|
|
"link": "https://docs.meilisearch.com/errors#invalid_filter"
|
|
});
|
|
index
|
|
.search(
|
|
json!({"filter": [["_geoDistance = Glass"]]}),
|
|
|response, code| {
|
|
assert_eq!(response, expected_response);
|
|
assert_eq!(code, 400);
|
|
},
|
|
)
|
|
.await;
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn filter_reserved_attribute_string() {
|
|
let server = Server::new().await;
|
|
let index = server.index("test");
|
|
|
|
index
|
|
.update_settings(json!({"filterableAttributes": ["title"]}))
|
|
.await;
|
|
|
|
let documents = DOCUMENTS.clone();
|
|
index.add_documents(documents, None).await;
|
|
index.wait_task(1).await;
|
|
|
|
let expected_response = json!({
|
|
"message": "`_geoDistance` is a reserved keyword and thus can't be used as a filter expression.\n1:13 _geoDistance = Glass",
|
|
"code": "invalid_filter",
|
|
"type": "invalid_request",
|
|
"link": "https://docs.meilisearch.com/errors#invalid_filter"
|
|
});
|
|
index
|
|
.search(
|
|
json!({"filter": "_geoDistance = Glass"}),
|
|
|response, code| {
|
|
assert_eq!(response, expected_response);
|
|
assert_eq!(code, 400);
|
|
},
|
|
)
|
|
.await;
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn sort_geo_reserved_attribute() {
|
|
let server = Server::new().await;
|
|
let index = server.index("test");
|
|
|
|
index
|
|
.update_settings(json!({"sortableAttributes": ["id"]}))
|
|
.await;
|
|
|
|
let documents = DOCUMENTS.clone();
|
|
index.add_documents(documents, None).await;
|
|
index.wait_task(1).await;
|
|
|
|
let expected_response = json!({
|
|
"message": "`_geo` is a reserved keyword and thus can't be used as a sort expression. Use the _geoPoint(latitude, longitude) built-in rule to sort on _geo field coordinates.",
|
|
"code": "invalid_sort",
|
|
"type": "invalid_request",
|
|
"link": "https://docs.meilisearch.com/errors#invalid_sort"
|
|
});
|
|
index
|
|
.search(
|
|
json!({
|
|
"sort": ["_geo:asc"]
|
|
}),
|
|
|response, code| {
|
|
assert_eq!(response, expected_response);
|
|
assert_eq!(code, 400);
|
|
},
|
|
)
|
|
.await;
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn sort_reserved_attribute() {
|
|
let server = Server::new().await;
|
|
let index = server.index("test");
|
|
|
|
index
|
|
.update_settings(json!({"sortableAttributes": ["id"]}))
|
|
.await;
|
|
|
|
let documents = DOCUMENTS.clone();
|
|
index.add_documents(documents, None).await;
|
|
index.wait_task(1).await;
|
|
|
|
let expected_response = json!({
|
|
"message": "`_geoDistance` is a reserved keyword and thus can't be used as a sort expression.",
|
|
"code": "invalid_sort",
|
|
"type": "invalid_request",
|
|
"link": "https://docs.meilisearch.com/errors#invalid_sort"
|
|
});
|
|
index
|
|
.search(
|
|
json!({
|
|
"sort": ["_geoDistance:asc"]
|
|
}),
|
|
|response, code| {
|
|
assert_eq!(response, expected_response);
|
|
assert_eq!(code, 400);
|
|
},
|
|
)
|
|
.await;
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn sort_unsortable_attribute() {
|
|
let server = Server::new().await;
|
|
let index = server.index("test");
|
|
|
|
index
|
|
.update_settings(json!({"sortableAttributes": ["id"]}))
|
|
.await;
|
|
|
|
let documents = DOCUMENTS.clone();
|
|
index.add_documents(documents, None).await;
|
|
index.wait_task(1).await;
|
|
|
|
let expected_response = json!({
|
|
"message": "Attribute `title` is not sortable. Available sortable attributes are: `id`.",
|
|
"code": "invalid_sort",
|
|
"type": "invalid_request",
|
|
"link": "https://docs.meilisearch.com/errors#invalid_sort"
|
|
});
|
|
index
|
|
.search(
|
|
json!({
|
|
"sort": ["title:asc"]
|
|
}),
|
|
|response, code| {
|
|
assert_eq!(response, expected_response);
|
|
assert_eq!(code, 400);
|
|
},
|
|
)
|
|
.await;
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn sort_invalid_syntax() {
|
|
let server = Server::new().await;
|
|
let index = server.index("test");
|
|
|
|
index
|
|
.update_settings(json!({"sortableAttributes": ["id"]}))
|
|
.await;
|
|
|
|
let documents = DOCUMENTS.clone();
|
|
index.add_documents(documents, None).await;
|
|
index.wait_task(1).await;
|
|
|
|
let expected_response = json!({
|
|
"message": "Invalid syntax for the sort parameter: expected expression ending by `:asc` or `:desc`, found `title`.",
|
|
"code": "invalid_sort",
|
|
"type": "invalid_request",
|
|
"link": "https://docs.meilisearch.com/errors#invalid_sort"
|
|
});
|
|
index
|
|
.search(
|
|
json!({
|
|
"sort": ["title"]
|
|
}),
|
|
|response, code| {
|
|
assert_eq!(response, expected_response);
|
|
assert_eq!(code, 400);
|
|
},
|
|
)
|
|
.await;
|
|
}
|
|
|
|
#[actix_rt::test]
|
|
async fn sort_unset_ranking_rule() {
|
|
let server = Server::new().await;
|
|
let index = server.index("test");
|
|
|
|
index
|
|
.update_settings(
|
|
json!({"sortableAttributes": ["title"], "rankingRules": ["proximity", "exactness"]}),
|
|
)
|
|
.await;
|
|
|
|
let documents = DOCUMENTS.clone();
|
|
index.add_documents(documents, None).await;
|
|
index.wait_task(1).await;
|
|
|
|
let expected_response = json!({
|
|
"message": "The sort ranking rule must be specified in the ranking rules settings to use the sort parameter at search time.",
|
|
"code": "invalid_sort",
|
|
"type": "invalid_request",
|
|
"link": "https://docs.meilisearch.com/errors#invalid_sort"
|
|
});
|
|
index
|
|
.search(
|
|
json!({
|
|
"sort": ["title:asc"]
|
|
}),
|
|
|response, code| {
|
|
assert_eq!(response, expected_response);
|
|
assert_eq!(code, 400);
|
|
},
|
|
)
|
|
.await;
|
|
}
|