Skip to content

Commit 92e23fa

Browse files
authored
Generic type for Document, search test (#42)
* ToTypesenseField macro full path * Document generic type * Rm unused * Refactor * Api tests * Search test * Clippy * Search test * Refactor macro
1 parent c435992 commit 92e23fa

25 files changed

+356
-331
lines changed

mocks/drop_collection.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ when:
44
header:
55
- name: X-TYPESENSE-API-KEY
66
value: VerySecretKey
7-
status: 200
87
then:
8+
status: 200
99
header:
1010
- name: content-type
1111
value: text/json

mocks/import_documents.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ when:
44
header:
55
- name: X-TYPESENSE-API-KEY
66
value: VerySecretKey
7-
body: "{\"company_name\": \"test\", \"num_employees\": 1, \"country\": \"c1\"}\n{\"company_name\": \"test2\", \"num_employees\": 2, \"country\": \"c2\"}"
7+
body: "{\"company_name\":\"test\",\"num_employees\":1,\"country\":\"c1\"}\n{\"company_name\":\"test2\",\"num_employees\":2,\"country\":\"c2\"}"
88
then:
99
status: 200
1010
header:

mocks/retrieve_all_collections.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ when:
44
header:
55
- name: X-TYPESENSE-API-KEY
66
value: VerySecretKey
7-
status: 200
87
then:
8+
status: 200
99
header:
1010
- name: content-type
1111
value: text/json

mocks/retrieve_collection.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ when:
44
header:
55
- name: X-TYPESENSE-API-KEY
66
value: VerySecretKey
7-
status: 200
87
then:
8+
status: 200
99
header:
1010
- name: content-type
1111
value: text/json

mocks/search_collection.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
when:
2+
method: GET
3+
path: /collections/companies/documents/search
4+
header:
5+
- name: X-TYPESENSE-API-KEY
6+
value: VerySecretKey
7+
query_param:
8+
- name: q
9+
value: test
10+
- name: query_by
11+
value: company_name
12+
then:
13+
status: 200
14+
header:
15+
- name: content-type
16+
value: application/text
17+
body: "{\"facet_counts\":[],\"found\":2,\"hits\":[{\"document\":{\"company_name\":\"test\",\"country\":\"c1\",\"id\":\"0\",\"num_employees\":1},\"highlight\":{\"company_name\":{\"matched_tokens\":[\"test\"],\"snippet\":\"<mark>test</mark>\"}},\"highlights\":[{\"field\":\"company_name\",\"matched_tokens\":[\"test\"],\"snippet\":\"<mark>test</mark>\"}],\"text_match\":578730123365711993,\"text_match_info\":{\"best_field_score\":\"1108091339008\",\"best_field_weight\":15,\"fields_matched\":1,\"score\":\"578730123365711993\",\"tokens_matched\":1}},{\"document\":{\"company_name\":\"test2\",\"country\":\"c2\",\"id\":\"1\",\"num_employees\":2},\"highlight\":{\"company_name\":{\"matched_tokens\":[\"test\"],\"snippet\":\"<mark>test</mark>2\"}},\"highlights\":[{\"field\":\"company_name\",\"matched_tokens\":[\"test\"],\"snippet\":\"<mark>test</mark>2\"}],\"text_match\":578730089005449337,\"text_match_info\":{\"best_field_score\":\"1108074561536\",\"best_field_weight\":15,\"fields_matched\":1,\"score\":\"578730089005449337\",\"tokens_matched\":1}}],\"out_of\":2,\"page\":1,\"request_params\":{\"collection_name\":\"companies\",\"per_page\":10,\"q\":\"test\"},\"search_cutoff\":false,\"search_time_ms\":0}"

typesense/Cargo.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ hmac = "0.12"
2323
serde = { version = "1", features = ["derive"] }
2424
serde_json = "1.0"
2525
sha2 = "0.10"
26-
typesense_derive = { version = "0.1.0", path="../typesense_derive", optional = true }
27-
typesense_codegen = { version = "0.25.0", path="../typesense_codegen" }
26+
typesense_derive = { version = "0.1.0", path = "../typesense_derive", optional = true }
27+
typesense_codegen = { version = "0.25.0", path = "../typesense_codegen" }
2828

2929
[dev-dependencies]
3030
dotenvy = "0.15"
@@ -42,3 +42,7 @@ wasm-bindgen-test = "0.3.23"
4242
name = "derive_tests"
4343
path = "tests/derive/lib.rs"
4444
required-features = ["derive"]
45+
46+
[[test]]
47+
name = "api_tests"
48+
path = "tests/api/lib.rs"

typesense/src/field/field_type.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ pub trait ToTypesenseField {
1414
#[macro_export]
1515
macro_rules! impl_to_typesense_field (
1616
($for:ty, $typesense_variant:expr) => {
17-
impl ToTypesenseField for $for {
17+
impl $crate::field::ToTypesenseField for $for {
1818
#[inline(always)]
1919
fn to_typesense_type() -> &'static str {
2020
$typesense_variant
2121
}
2222
}
2323
};
2424
($for:ty, $typesense_variant:expr, $any:ident) => {
25-
impl<$any> ToTypesenseField for $for {
25+
impl<$any> $crate::field::ToTypesenseField for $for {
2626
#[inline(always)]
2727
fn to_typesense_type() -> &'static str {
2828
$typesense_variant
Lines changed: 20 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
#![allow(dead_code)]
22

3+
use super::Config;
34
use serde::{Deserialize, Serialize};
45
use typesense::document::Document;
56
use typesense::Typesense;
67
use typesense_codegen::apis::collections_api;
7-
use typesense_codegen::apis::configuration::{ApiKey, Configuration};
8-
use typesense_codegen::models::CollectionResponse;
9-
use typesense_codegen::models::CollectionSchema;
8+
use typesense_codegen::models::{CollectionResponse, CollectionSchema};
109

1110
#[derive(Typesense, Serialize, Deserialize)]
1211
#[typesense(collection_name = "companies", default_sorting_field = "num_employees")]
@@ -30,18 +29,9 @@ fn schema_to_resp(schema: CollectionSchema, resp: &CollectionResponse) -> Collec
3029
}
3130
}
3231

33-
async fn create_collection(host: impl Into<String>, api_key: impl Into<String>) {
34-
let config = Configuration {
35-
base_path: host.into(),
36-
api_key: Some(ApiKey {
37-
prefix: None,
38-
key: api_key.into(),
39-
}),
40-
..Default::default()
41-
};
42-
32+
async fn create_collection() {
4333
let collection_schema_response =
44-
collections_api::create_collection(&config, Company::collection_schema())
34+
collections_api::create_collection(Config::get(), Company::collection_schema())
4535
.await
4636
.unwrap();
4737

@@ -52,17 +42,8 @@ async fn create_collection(host: impl Into<String>, api_key: impl Into<String>)
5242
);
5343
}
5444

55-
async fn get_collection(host: impl Into<String>, api_key: impl Into<String>) {
56-
let config = Configuration {
57-
base_path: host.into(),
58-
api_key: Some(ApiKey {
59-
prefix: None,
60-
key: api_key.into(),
61-
}),
62-
..Default::default()
63-
};
64-
65-
let collection_schema_response = collections_api::get_collection(&config, "companies")
45+
async fn get_collection() {
46+
let collection_schema_response = collections_api::get_collection(Config::get(), "companies")
6647
.await
6748
.unwrap();
6849

@@ -73,17 +54,8 @@ async fn get_collection(host: impl Into<String>, api_key: impl Into<String>) {
7354
);
7455
}
7556

76-
async fn delete_collection(host: impl Into<String>, api_key: impl Into<String>) {
77-
let config = Configuration {
78-
base_path: host.into(),
79-
api_key: Some(ApiKey {
80-
prefix: None,
81-
key: api_key.into(),
82-
}),
83-
..Default::default()
84-
};
85-
86-
let collection_schema_response = collections_api::delete_collection(&config, "companies")
57+
async fn delete_collection() {
58+
let collection_schema_response = collections_api::delete_collection(Config::get(), "companies")
8759
.await
8860
.unwrap();
8961

@@ -94,17 +66,10 @@ async fn delete_collection(host: impl Into<String>, api_key: impl Into<String>)
9466
);
9567
}
9668

97-
async fn get_collections(host: impl Into<String>, api_key: impl Into<String>) {
98-
let config = Configuration {
99-
base_path: host.into(),
100-
api_key: Some(ApiKey {
101-
prefix: None,
102-
key: api_key.into(),
103-
}),
104-
..Default::default()
105-
};
106-
107-
let collection_schema_response = collections_api::get_collections(&config).await.unwrap();
69+
async fn get_collections() {
70+
let collection_schema_response = collections_api::get_collections(Config::get())
71+
.await
72+
.unwrap();
10873

10974
assert_eq!(collection_schema_response.len(), 2);
11075
}
@@ -115,42 +80,22 @@ mod tokio_test {
11580

11681
#[tokio::test]
11782
async fn create_collection_tokio() {
118-
let _ = dotenvy::dotenv();
119-
120-
let host = std::env::var("URL").expect("URL must be present in .env");
121-
let api_key = std::env::var("API_KEY").expect("API_KEY must be present in .env");
122-
123-
create_collection(host, api_key).await
83+
create_collection().await
12484
}
12585

12686
#[tokio::test]
12787
async fn get_collection_tokio() {
128-
let _ = dotenvy::dotenv();
129-
130-
let host = std::env::var("URL").expect("URL must be present in .env");
131-
let api_key = std::env::var("API_KEY").expect("API_KEY must be present in .env");
132-
133-
get_collection(host, api_key).await
88+
get_collection().await
13489
}
13590

13691
#[tokio::test]
13792
async fn delete_collection_tokio() {
138-
let _ = dotenvy::dotenv();
139-
140-
let host = std::env::var("URL").expect("URL must be present in .env");
141-
let api_key = std::env::var("API_KEY").expect("API_KEY must be present in .env");
142-
143-
delete_collection(host, api_key).await
93+
delete_collection().await
14494
}
14595

14696
#[tokio::test]
14797
async fn get_collections_tokio() {
148-
let _ = dotenvy::dotenv();
149-
150-
let host = std::env::var("URL").expect("URL must be present in .env");
151-
let api_key = std::env::var("API_KEY").expect("API_KEY must be present in .env");
152-
153-
get_collections(host, api_key).await
98+
get_collections().await
15499
}
155100
}
156101

@@ -161,34 +106,31 @@ mod wasm_test {
161106

162107
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
163108

164-
const HOST: &str = "http://localhost:5000";
165-
const API_KEY: &str = "VerySecretKey";
166-
167109
#[wasm_bindgen_test]
168110
async fn create_collection_wasm() {
169111
console_error_panic_hook::set_once();
170112

171-
create_collection(HOST, API_KEY).await
113+
create_collection().await
172114
}
173115

174116
#[wasm_bindgen_test]
175117
async fn get_collection_wasm() {
176118
console_error_panic_hook::set_once();
177119

178-
get_collection(HOST, API_KEY).await
120+
get_collection().await
179121
}
180122

181123
#[wasm_bindgen_test]
182124
async fn delete_collection_wasm() {
183125
console_error_panic_hook::set_once();
184126

185-
delete_collection(HOST, API_KEY).await
127+
delete_collection().await
186128
}
187129

188130
#[wasm_bindgen_test]
189131
async fn get_collections_wasm() {
190132
console_error_panic_hook::set_once();
191133

192-
get_collections(HOST, API_KEY).await
134+
get_collections().await
193135
}
194136
}

typesense/tests/api/documents.rs

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#![allow(dead_code)]
2+
3+
use super::Config;
4+
use serde::{Deserialize, Serialize};
5+
use typesense::document::Document;
6+
use typesense::models::SearchParameters;
7+
use typesense::Typesense;
8+
use typesense_codegen::apis::documents_api;
9+
10+
#[derive(Typesense, Serialize, Deserialize)]
11+
#[typesense(collection_name = "companies", default_sorting_field = "num_employees")]
12+
struct Company {
13+
company_name: String,
14+
num_employees: i32,
15+
#[typesense(facet)]
16+
country: String,
17+
}
18+
19+
async fn import_documents() {
20+
let documents = [
21+
Company {
22+
company_name: "test".to_owned(),
23+
num_employees: 1,
24+
country: "c1".to_owned(),
25+
},
26+
Company {
27+
company_name: "test2".to_owned(),
28+
num_employees: 2,
29+
country: "c2".to_owned(),
30+
},
31+
]
32+
.map(|c| serde_json::to_string(&c).unwrap())
33+
.join("\n");
34+
35+
let resp = documents_api::import_documents(
36+
Config::get(),
37+
&Company::collection_schema().name,
38+
documents,
39+
None,
40+
)
41+
.await
42+
.unwrap();
43+
44+
assert_eq!(&resp, "{\"success\":true}\n{\"success\":true}");
45+
}
46+
47+
async fn search_collection() {
48+
let search = SearchParameters {
49+
q: "test".to_owned(),
50+
query_by: "company_name".to_owned(),
51+
..Default::default()
52+
};
53+
54+
let resp = documents_api::search_collection::<Company>(
55+
Config::get(),
56+
&Company::collection_schema().name,
57+
search,
58+
)
59+
.await
60+
.unwrap();
61+
62+
assert_eq!(resp.found, Some(2));
63+
assert_eq!(
64+
resp.hits
65+
.unwrap()
66+
.first()
67+
.unwrap()
68+
.document
69+
.as_ref()
70+
.unwrap()
71+
.company_name,
72+
"test".to_owned()
73+
);
74+
}
75+
76+
#[cfg(all(feature = "tokio_test", not(target_arch = "wasm32")))]
77+
mod tokio_test {
78+
use super::*;
79+
80+
#[tokio::test]
81+
async fn import_documents_tokio() {
82+
import_documents().await
83+
}
84+
85+
#[tokio::test]
86+
async fn search_collection_tokio() {
87+
search_collection().await
88+
}
89+
}
90+
91+
#[cfg(target_arch = "wasm32")]
92+
mod wasm_test {
93+
use super::*;
94+
use wasm_bindgen_test::wasm_bindgen_test;
95+
96+
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
97+
98+
#[wasm_bindgen_test]
99+
async fn import_documents_wasm() {
100+
console_error_panic_hook::set_once();
101+
102+
import_documents().await
103+
}
104+
105+
#[wasm_bindgen_test]
106+
async fn search_collection_wasm() {
107+
console_error_panic_hook::set_once();
108+
109+
search_collection().await
110+
}
111+
}

0 commit comments

Comments
 (0)