extern crate log; extern crate rocket; extern crate aw_datastore; extern crate aw_server; #[cfg(test)] mod api_tests { use std::collections::HashMap; use rocket::http::{ContentType, Header, Status}; use serde_json::{json, Value}; use aw_server::config; use aw_server::endpoints; use aw_models::{Bucket, BucketsExport}; use rocket::local::blocking::Client; fn setup_testserver() -> rocket::Rocket { let state = endpoints::ServerState { datastore: aw_datastore::Datastore::new_in_memory(false), asset_resolver: endpoints::AssetResolver::new(None), device_id: "test_id".to_string(), }; let aw_config = config::AWConfig::default(); endpoints::build_rocket(state, aw_config) } #[test] fn export_includes_pending_writes_and_preserves_headers_and_missing_bucket_errors() { let server = setup_testserver(); let datastore = server .state::() .unwrap() .datastore .clone(); let bucket: Bucket = serde_json::from_value(json!({ "id": "live", "type": "test", "client": "test", "hostname": "test" })) .unwrap(); datastore.create_bucket(&bucket).unwrap(); let event = aw_models::Event::default(); let inserted = datastore.insert_events("live", &[event]).unwrap(); // No force_commit: exports must see writes acknowledged by the worker. let client = Client::untracked(server).unwrap(); for path in ["/api/0/export", "/api/0/buckets/live/export"] { let response = client .get(path) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(response.status(), Status::Ok); assert_eq!(response.content_type(), Some(ContentType::JSON)); assert_eq!( response.headers().get_one("Content-Disposition"), Some("attachment; filename=aw-bucket-export_live.json") ); let body: Value = serde_json::from_str(&response.into_string().unwrap()).unwrap(); assert_eq!( body["buckets"]["live"]["events"], serde_json::to_value(&inserted).unwrap() ); } let response = client .get("/api/0/buckets/missing/export") .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(response.status(), Status::NotFound); let body: Value = serde_json::from_str(&response.into_string().unwrap()).unwrap(); assert!(body["message"].as_str().unwrap().contains("does not exist")); } #[test] fn test_bucket() { let server = setup_testserver(); let client = Client::untracked(server).expect("valid instance"); // Get empty list of buckets let mut res = client .get("/api/0/buckets/") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); let buckets: HashMap = serde_json::from_str(&res.into_string().unwrap()).unwrap(); assert_eq!(buckets.len(), 0); // Try to fetch non-existing bucket res = client .get("/api/0/buckets/id") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::NotFound); // Create bucket res = client .post("/api/0/buckets/id") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .body( r#"{ "id": "id", "type": "type", "client": "client", "hostname": "hostname" }"#, ) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); // Try to create bucket which already exists res = client .post("/api/0/buckets/id") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .body( r#"{ "id": "id", "type": "type", "client": "client", "hostname": "hostname" }"#, ) .dispatch(); assert_eq!(res.status(), rocket::http::Status::NotModified); assert_eq!( res.into_string().unwrap(), r#"{"message":"Bucket 'id' already exists"}"# ); // Get list of buckets (1 bucket) res = client .get("/api/0/buckets/") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); let buckets: HashMap = serde_json::from_str(&res.into_string().unwrap()).unwrap(); assert_eq!(buckets.len(), 1); let bucket = buckets.get("id").unwrap(); assert_eq!(bucket.id, "id"); assert_eq!(bucket._type, "type"); assert_eq!(bucket.client, "client"); assert_eq!(bucket.hostname, "hostname"); assert!(bucket.events.is_none()); assert_eq!(bucket.metadata.start, None); assert_eq!(bucket.metadata.end, None); // Get newly created bucket res = client .get("/api/0/buckets/id") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); // Validate output let bucket: Bucket = serde_json::from_str(&res.into_string().unwrap()).unwrap(); assert_eq!(bucket.id, "id"); assert_eq!(bucket._type, "type"); assert_eq!(bucket.client, "client"); assert_eq!(bucket.hostname, "hostname"); assert!(bucket.events.is_none()); assert_eq!(bucket.metadata.start, None); assert_eq!(bucket.metadata.end, None); // Get non-existing bucket res = client .get("/api/0/buckets/invalid_bucket") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::NotFound); // Delete bucket res = client .delete("/api/0/buckets/id") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); // Try (and fail) to get deleted bucket res = client .get("/api/0/buckets/id") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::NotFound); // Get empty list of buckets let res = client .get("/api/0/buckets/") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); let buckets: HashMap = serde_json::from_str(&res.into_string().unwrap()).unwrap(); assert_eq!(buckets.len(), 0); } #[test] fn test_bucket_hostname_validation() { let server = setup_testserver(); let client = Client::untracked(server).expect("valid instance"); // A client-supplied hostname containing whitespace is rejected let res = client .post("/api/0/buckets/spacey") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .body( r#"{ "id": "spacey", "type": "type", "client": "client", "hostname": "my phone" }"#, ) .dispatch(); assert_eq!(res.status(), rocket::http::Status::BadRequest); assert_eq!( res.into_string().unwrap(), r#"{"message":"Invalid hostname \"my phone\": hostname may not contain whitespace"}"# ); // The rejected bucket was not created let res = client .get("/api/0/buckets/spacey") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::NotFound); // An already-existing bucket keeps the established "already exists" response // even if the re-create payload carries a whitespace hostname. Watchers // idempotently re-create their bucket on startup, so a legacy bucket stored // under a spacey hostname must not start hard-failing every boot. let res = client .post("/api/0/buckets/existing") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .body( r#"{ "id": "existing", "type": "type", "client": "client", "hostname": "hostname" }"#, ) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); let res = client .post("/api/0/buckets/existing") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .body( r#"{ "id": "existing", "type": "type", "client": "client", "hostname": "my phone" }"#, ) .dispatch(); assert_eq!(res.status(), rocket::http::Status::NotModified); // The "!local" sentinel bypasses validation (resolved server-side) let res = client .post("/api/0/buckets/localbucket") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .body( r#"{ "id": "localbucket", "type": "type", "client": "client", "hostname": "!local" }"#, ) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); } #[test] fn test_events() { let server = setup_testserver(); let client = Client::untracked(server).expect("valid instance"); // Create bucket let res = client .post("/api/0/buckets/id") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .body( r#"{ "id": "id", "type": "type", "client": "client", "hostname": "hostname" }"#, ) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); // Insert a single event let res = client .post("/api/0/buckets/id/events") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .body( r#"[{ "timestamp": "2018-01-01T01:01:01Z", "duration": 1.0, "data": {} }]"#, ) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); assert_eq!( res.into_string().unwrap(), r#"[{"id":1,"timestamp":"2018-01-01T01:01:01Z","duration":1.0,"data":{}}]"# ); // Get inserted event let res = client .get("/api/0/buckets/id/events") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); assert_eq!( res.into_string().unwrap(), r#"[{"id":1,"timestamp":"2018-01-01T01:01:01Z","duration":1.0,"data":{}}]"# ); // Heartbeat let res = client .post("/api/0/buckets/id/heartbeat?pulsetime=2") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .body( r#"{ "timestamp": "2018-01-01T01:01:02Z", "duration": 1.0, "data": {} }"#, ) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); // After the fix for #559, the heartbeat response includes the DB event ID assert_eq!( res.into_string().unwrap(), r#"{"id":1,"timestamp":"2018-01-01T01:01:01Z","duration":2.0,"data":{}}"# ); // Get heartbeat event let res = client .get("/api/0/buckets/id/events") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); assert_eq!( res.into_string().unwrap(), r#"[{"id":1,"timestamp":"2018-01-01T01:01:01Z","duration":2.0,"data":{}}]"# ); // Delete event client .delete("/api/0/buckets/id/events/1") .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); // Get eventcount let res = client .get("/api/0/buckets/id/events/count") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); assert_eq!(res.into_string().unwrap(), "0"); // Delete bucket let res = client .delete("/api/0/buckets/id") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); } #[test] fn test_import_export() { let server = setup_testserver(); let client = Client::untracked(server).expect("valid instance"); // Import bucket let res = client .post("/api/0/import") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .body( r#"{"buckets": {"id1": { "id": "id1", "type": "type", "client": "client", "hostname": "hostname", "events": [{ "timestamp":"2000-01-01T00:00:00Z", "duration":1.0, "data": {} }] }}}"#, ) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); // Import already existing bucket with a new event — should merge instead of fail let res = client .post("/api/0/import") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .body( r#"{"buckets": {"id1": { "id": "id1", "type": "type", "client": "client", "hostname": "hostname", "events": [{ "timestamp":"2000-01-02T00:00:00Z", "duration":1.0, "data": {} }] }}}"#, ) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); // Verify events were merged — bucket should now have 2 events let res = client .get("/api/0/buckets/id1/events") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); let events: serde_json::Value = serde_json::from_str(&res.into_string().unwrap()).unwrap(); assert_eq!(events.as_array().unwrap().len(), 2); // Re-import the first event again — should be idempotent (no duplicate created) let res = client .post("/api/0/import") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .body( r#"{"buckets": {"id1": { "id": "id1", "type": "type", "client": "client", "hostname": "hostname", "events": [{ "timestamp":"2000-01-01T00:00:00Z", "duration":1.0, "data": {} }] }}}"#, ) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); // Count should still be 2, not 3 — re-import is idempotent let res = client .get("/api/0/buckets/id1/events") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); let events: serde_json::Value = serde_json::from_str(&res.into_string().unwrap()).unwrap(); assert_eq!( events.as_array().unwrap().len(), 2, "Re-importing the same event should be idempotent" ); // Import a narrower event fully contained within an existing longer event. // This should be preserved as a distinct event, not dropped by clipped dedup. let res = client .post("/api/0/import") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .body( r#"{"buckets": {"id1": { "id": "id1", "type": "type", "client": "client", "hostname": "hostname", "events": [{ "timestamp":"2000-01-01T00:00:30Z", "duration":30.0, "data": {} }] }}}"#, ) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); let res = client .get("/api/0/buckets/id1/events") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); let events: serde_json::Value = serde_json::from_str(&res.into_string().unwrap()).unwrap(); assert_eq!( events.as_array().unwrap().len(), 3, "Contained event should not be dropped by clipped dedup" ); // Export single created bucket let res = client .get("/api/0/buckets/id1/export") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); let export: BucketsExport = serde_json::from_str(&res.into_string().unwrap()).unwrap(); // Delete bucket so we can import it again let res = client .delete("/api/0/buckets/id1") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); // Import exported bucket again but with multipart/form-data let boundary_start = b"--a\r\n"; let disposition = b"Content-Disposition: form-data; name=\"buckets.json\"\r\n"; let content_type = b"Content-Type: application/json\r\n"; let data_start = b"\r\n"; let content = serde_json::to_vec(&export).unwrap(); let boundary_end = b"\r\n--a--"; let sum = [ &boundary_start[..], &disposition[..], &content_type[..], &data_start[..], &content[..], &boundary_end[..], ] .concat(); let res = client .post("/api/0/import") .header(Header::new( "Content-Type", "multipart/form-data; boundary=a", )) .header(Header::new("Host", "127.0.0.1:5600")) .body(&sum[..]) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); // Get created bucket let res = client .get("/api/0/buckets/id1") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); println!("{:?}", res.into_string()); // Export all buckets let res = client .get("/api/0/export") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); let export: BucketsExport = serde_json::from_str(&res.into_string().unwrap()).unwrap(); let mut buckets = export.buckets; assert_eq!(buckets.len(), 1); let b = buckets.remove("id1").unwrap(); assert_eq!( b.events.unwrap().take_inner().len(), 3, "Export should preserve the contained event added during merge testing" ); assert_eq!(buckets.len(), 0); } #[test] fn test_query() { let server = setup_testserver(); let client = Client::untracked(server).expect("valid instance"); // Minimal query let res = client .post("/api/0/query") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .body( r#"{ "timeperiods": ["2000-01-01T00:00:00Z/2020-01-01T00:00:00Z"], "query": ["return 1;"] }"#, ) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); assert_eq!(res.into_string().unwrap(), r#"[1.0]"#); // Create bucket to query later let res = client .post("/api/0/buckets/id") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .body( r#"{ "id": "id", "type": "type", "client": "client", "hostname": "hostname" }"#, ) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); // Insert a event to query later let res = client .post("/api/0/buckets/id/events") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .body( r#"[{ "timestamp": "2018-01-01T01:01:01Z", "duration": 1.0, "data": {} }]"#, ) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); // Query events let res = client .post("/api/0/query") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .body( r#"{ "timeperiods": ["2000-01-01T00:00:00Z/2020-01-01T00:00:00Z"], "query": ["return query_bucket(\"id\");"] }"#, ) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); assert_eq!( res.into_string().unwrap(), r#"[[{"data":{},"duration":1.0,"id":1,"timestamp":"2018-01-01T01:01:01Z"}]]"# ); // Test error let res = client .post("/api/0/query") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .body( r#"{ "timeperiods": ["2000-01-01T00:00:00Z/2020-01-01T00:00:00Z"], "query": [""] }"#, ) .dispatch(); assert_eq!(res.status(), rocket::http::Status::BadRequest); assert_eq!(res.into_string().unwrap(), r#"{"message":"EmptyQuery"}"#); } fn set_setting_request(client: &Client, key: &str, value: &Value) -> Status { let body = serde_json::to_string(value).unwrap(); let res = client .post(format!("/api/0/settings/{}", key)) .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .body(body) .dispatch(); res.status() } #[test] fn test_illegally_long_key() { let server = setup_testserver(); let client = Client::untracked(server).expect("valid instance"); // Test getting not found (getting nonexistent key) let key = "thisisaverylongkthisisaverylongkthisisaverylongkthisisaverylongkthisisaverylongkthisisaverylongkthisisaverylongkthisisaverylongk"; let value = json!("test_value"); let res = set_setting_request(&client, key, &value); assert_eq!(res, rocket::http::Status::BadRequest); } #[test] fn test_setting_setting() { let server = setup_testserver(); let client = Client::untracked(server).expect("valid instance"); // Test value creation let key = "test_key"; let value = json!("test_value"); let response_status = set_setting_request(&client, key, &value); assert_eq!(response_status, rocket::http::Status::Created); } #[test] fn test_get_unset_setting() { let server = setup_testserver(); let client = Client::untracked(server).expect("valid instance"); // Test getting not found (getting nonexistent key) let key = "non_existent_key"; let res = client .get(format!("/api/0/settings/{}", key)) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); assert_eq!(res.into_string().unwrap(), "null") } #[test] fn test_get_settings() { let server = setup_testserver(); let client = Client::untracked(server).expect("valid instance"); let key1 = "test_key"; let key2 = "test_key_2"; let value = json!("test_value"); let response1_status = set_setting_request(&client, key1, &value); assert_eq!(response1_status, rocket::http::Status::Created); let response2_status = set_setting_request(&client, key2, &value); assert_eq!(response2_status, rocket::http::Status::Created); let res = client .get("/api/0/settings") .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); let deserialized: Value = serde_json::from_str(&res.into_string().unwrap()).unwrap(); let expected: Value = serde_json::from_str(r#"{"test_key_2":"test_value","test_key":"test_value"}"#).unwrap(); assert_eq!(deserialized, expected); } #[test] fn test_get_setting() { let server = setup_testserver(); let client = Client::untracked(server).expect("valid instance"); let key = "test_key"; let value = json!("test_value"); let response_status = set_setting_request(&client, key, &value); assert_eq!(response_status, rocket::http::Status::Created); // Test getting let res = client .get(format!("/api/0/settings/{}", key)) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); let deserialized: Value = serde_json::from_str(&res.into_string().unwrap()).unwrap(); assert_eq!(deserialized, value); } #[test] fn test_get_setting_dotted_key() { // HTTP accepts dotted keys; JNI getSetting must use the same grammar // (ActivityWatch/aw-server-rust#653 Greptile: don't reject '.'). let server = setup_testserver(); let client = Client::untracked(server).expect("valid instance"); let key = "nested.like.key"; let value = json!("dotted_value"); assert_eq!( set_setting_request(&client, key, &value), rocket::http::Status::Created ); let res = client .get(format!("/api/0/settings/{}", key)) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); let deserialized: Value = serde_json::from_str(&res.into_string().unwrap()).unwrap(); assert_eq!(deserialized, value); } #[test] fn test_get_setting_list() { let server = setup_testserver(); let client = Client::untracked(server).expect("valid instance"); // Test array let key = "test_key_array"; let value = json!([1, 2, 3]); let response_status = set_setting_request(&client, key, &value); assert_eq!(response_status, rocket::http::Status::Created); let res = client .get(format!("/api/0/settings/{}", key)) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); let deserialized: Value = serde_json::from_str(&res.into_string().unwrap()).unwrap(); assert_eq!(deserialized, value); } #[test] fn test_get_setting_dict() { let server = setup_testserver(); let client = Client::untracked(server).expect("valid instance"); // Test dict let key = "test_key_dict"; let value = json!({"key": "value", "another_key": "another value"}); let response_status = set_setting_request(&client, key, &value); assert_eq!(response_status, rocket::http::Status::Created); let res = client .get("/api/0/settings/test_key_dict") .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); let deserialized: Value = serde_json::from_str(&res.into_string().unwrap()).unwrap(); assert_eq!(deserialized, value); } #[test] fn test_set_setting() { let server = setup_testserver(); let client = Client::untracked(server).expect("valid instance"); let key = "test_key"; let value1 = json!("test_value"); let value2 = json!("changed_test_value"); let post_1_status = set_setting_request(&client, key, &value1); assert_eq!(post_1_status, rocket::http::Status::Created); let res = client .get(format!("/api/0/settings/{}", key)) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); let deserialized: Value = serde_json::from_str(&res.into_string().unwrap()).unwrap(); assert_eq!(deserialized, value1); let post_2_status = set_setting_request(&client, key, &value2); assert_eq!(post_2_status, rocket::http::Status::Created); let res = client .get("/api/0/settings/test_key") .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); let new_deserialized: Value = serde_json::from_str(&res.into_string().unwrap()).unwrap(); assert_eq!(new_deserialized, value2); } #[test] fn test_delete_setting() { let server = setup_testserver(); let client = Client::untracked(server).expect("valid instance"); let value = json!("test_value"); let response_status = set_setting_request(&client, "test_key", &value); assert_eq!(response_status, rocket::http::Status::Created); // Test deleting let res = client .delete("/api/0/settings/test_key") .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); let res = client .get("/api/0/settings/test_key") .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); assert_eq!(res.into_string().unwrap(), "null"); } #[test] fn test_cors_catching() { let server = setup_testserver(); let client = Client::untracked(server).expect("valid instance"); let res = client .options("/api/0/buckets/") .header(ContentType::JSON) .header(Header::new("Host", "127.0.0.1:5600")) .dispatch(); assert_eq!(res.status(), rocket::http::Status::Ok); } }