mirror of
https://github.com/hanzoai/insights.git
synced 2026-10-30 16:15:31 +00:00
The tree was a debranded snapshot of upstream taken around 2026-02-20, and upstream has moved about five months since. This replaces it with upstream master, mechanically re-derived: bin/debrand does the rename, and the pipeline and squashed migrations are restored from the shipped tree. Not a merge. The previous import replaced the tree wholesale in a single commit, so there is no shared content history to merge against. Reproducing the rename on the new tree is what actually converges. What survives: .hanzo/workflows, the Dockerfiles and bin/docker* entrypoints, compose files, LLM.md, and insights/migrations. The squashed initial migration is load-bearing — the live database records it by name, so upstream's ~918 individual migrations cannot come back. Nine products are dropped as unreferenced. Twenty-one more that we do not run are kept anyway because the core app still imports them; unpicking those is a refactor and does not belong in a rebase. This base does not build yet, and the reasons are not in the rename: upstream now wants Python 3.13.13 against our 3.12.12 and Django 5.2 against our 4.2, and the dependency manifests still name upstream packages that we republish under our own names. Those are decisions, not renames.
406 lines
12 KiB
Rust
406 lines
12 KiB
Rust
#[path = "common/integration_utils.rs"]
|
|
mod integration_utils;
|
|
use integration_utils::{
|
|
base64_payload, execute_test, form_data_base64_payload, form_lz64_urlencoded_payload,
|
|
form_urlencoded_payload, gzipped_payload, lz64_payload, plain_json_payload, Method, TestCase,
|
|
BATCH_EVENTS_JSON, BATCH_EVENTS_WITH_HEATMAP_JSON, DEFAULT_TEST_TIME, SINGLE_EVENT_JSON,
|
|
};
|
|
|
|
use axum::http::StatusCode;
|
|
use capture::config::CaptureMode;
|
|
|
|
//
|
|
// The /i/v0/e/ and /batch/ endpoints are all processed by event_next
|
|
// and support the same request payload shapes and encodings.
|
|
//
|
|
|
|
#[tokio::test]
|
|
async fn test_i_v0_e_endpoint() {
|
|
let base_path = "/i/v0/e";
|
|
|
|
// NOT currently supported by new capture endpoint handlers
|
|
for mut unit in get_cases() {
|
|
unit.base_path = base_path;
|
|
execute_test(&unit).await;
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_i_v0_e_endpoint_post() {
|
|
let base_path = "/i/v0/e";
|
|
|
|
// POST requests with payload in body, metadata in POST form or GET params
|
|
for mut unit in post_cases() {
|
|
unit.base_path = base_path;
|
|
execute_test(&unit).await;
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_i_v0_e_endpoint_get_with_body() {
|
|
// GET requests with a body payload are treated identically to POST requests
|
|
let mut get_with_body_cases = post_cases();
|
|
|
|
get_with_body_cases
|
|
.iter_mut()
|
|
.for_each(|tc: &mut TestCase| {
|
|
tc.base_path = "/i/v0/e";
|
|
tc.method = Method::GetWithBody;
|
|
tc.title = tc.title.replace("post-", "get_with_body-");
|
|
});
|
|
|
|
for unit in get_with_body_cases {
|
|
execute_test(&unit).await;
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_batch_endpoint_get() {
|
|
let base_path = "/batch";
|
|
|
|
// NOT currently supported by new capture endpoint handlers
|
|
for mut unit in get_cases() {
|
|
unit.base_path = base_path;
|
|
execute_test(&unit).await;
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_batch_endpoint_post() {
|
|
let base_path = "/batch";
|
|
|
|
// POST requests with payload in body, metadata in POST form or GET params
|
|
for mut unit in post_cases() {
|
|
unit.base_path = base_path;
|
|
execute_test(&unit).await;
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_batch_endpoint_get_with_body() {
|
|
// GET requests with a body payload are treated identically to POST requests
|
|
let mut get_with_body_cases = post_cases();
|
|
|
|
get_with_body_cases
|
|
.iter_mut()
|
|
.for_each(|tc: &mut TestCase| {
|
|
tc.base_path = "/batch";
|
|
tc.method = Method::GetWithBody;
|
|
tc.title = tc.title.replace("post-", "get_with_body-");
|
|
});
|
|
|
|
for unit in get_with_body_cases {
|
|
execute_test(&unit).await;
|
|
}
|
|
}
|
|
|
|
fn post_cases() -> Vec<TestCase> {
|
|
let units = vec![
|
|
// single event payload tests
|
|
|
|
// plain JSON POST body
|
|
TestCase::new(
|
|
// test case title
|
|
"new_post-simple-single-event-payload".to_string(),
|
|
// default fixed time for test Router & event handler
|
|
DEFAULT_TEST_TIME,
|
|
// capture-rs service mode
|
|
CaptureMode::Events,
|
|
// capture-rs target endpoint (overridden for multi-endpoint tests like these)
|
|
"",
|
|
// JSON payload to use as input
|
|
SINGLE_EVENT_JSON,
|
|
// request submission type; one of POST or GET only for these integration tests
|
|
Method::Post,
|
|
// compression "hint" (as supplied by some SDKs)
|
|
None,
|
|
// $lib_version "hint" (as supplied by some SDKs outside of event props)
|
|
None,
|
|
// request Content-Type
|
|
"application/json",
|
|
// determine how to eval the response - do we expect to succeed or fail this call?
|
|
StatusCode::OK,
|
|
// type of pre-processing and formatting to apply to payload
|
|
Box::new(plain_json_payload),
|
|
),
|
|
// plain base64'd JSON payload in POST body
|
|
TestCase::new(
|
|
"new_post-base64-single-event-payload".to_string(),
|
|
DEFAULT_TEST_TIME,
|
|
CaptureMode::Events,
|
|
"",
|
|
SINGLE_EVENT_JSON,
|
|
Method::Post,
|
|
Some("base64"),
|
|
None,
|
|
"application/json",
|
|
StatusCode::OK,
|
|
Box::new(base64_payload),
|
|
),
|
|
// base64'd JSON payload w/o SDK encoding hint
|
|
TestCase::new(
|
|
"new_post-base64-no-hint-single-event-payload".to_string(),
|
|
DEFAULT_TEST_TIME,
|
|
CaptureMode::Events,
|
|
"",
|
|
SINGLE_EVENT_JSON,
|
|
Method::Post,
|
|
None, // no compression hint; handling must auto-detect
|
|
None,
|
|
"text/plain",
|
|
StatusCode::OK,
|
|
Box::new(base64_payload),
|
|
),
|
|
// GZIP'd JSON single event payload
|
|
TestCase::new(
|
|
"new_post-gzip-single-event-payload".to_string(),
|
|
DEFAULT_TEST_TIME,
|
|
CaptureMode::Events,
|
|
"",
|
|
SINGLE_EVENT_JSON,
|
|
Method::Post,
|
|
Some("gzip"),
|
|
None,
|
|
"application/json",
|
|
StatusCode::OK,
|
|
Box::new(gzipped_payload),
|
|
),
|
|
// GZIP'd single event JSON payload w/o SDK encoding hint
|
|
TestCase::new(
|
|
"new_post-gzip-no-hint-single-event-payload".to_string(),
|
|
DEFAULT_TEST_TIME,
|
|
CaptureMode::Events,
|
|
"",
|
|
SINGLE_EVENT_JSON,
|
|
Method::Post,
|
|
None, // no compression hint; handling must auto-detect
|
|
None,
|
|
"text/plain",
|
|
StatusCode::OK,
|
|
Box::new(gzipped_payload),
|
|
),
|
|
// single event JSON payload in POST form with "data" attribute base64 encoded
|
|
TestCase::new(
|
|
"new_post-form-data-base64-event-payload".to_string(),
|
|
DEFAULT_TEST_TIME,
|
|
CaptureMode::Events,
|
|
"",
|
|
SINGLE_EVENT_JSON,
|
|
Method::Post,
|
|
None,
|
|
None,
|
|
"application/x-www-form-urlencoded",
|
|
StatusCode::BAD_REQUEST,
|
|
Box::new(form_data_base64_payload),
|
|
),
|
|
// single event JSON payload submitted as POST form
|
|
TestCase::new(
|
|
"new_post-form-urlencoded-event-payload".to_string(),
|
|
DEFAULT_TEST_TIME,
|
|
CaptureMode::Events,
|
|
"",
|
|
SINGLE_EVENT_JSON,
|
|
Method::Post,
|
|
None,
|
|
None,
|
|
"application/x-www-form-urlencoded",
|
|
StatusCode::OK,
|
|
Box::new(form_urlencoded_payload),
|
|
),
|
|
// single event JSON payload submitted as LZ64'd value in POST form
|
|
TestCase::new(
|
|
"new_post-form-lz64-urlencoded-event-payload".to_string(),
|
|
DEFAULT_TEST_TIME,
|
|
CaptureMode::Events,
|
|
"",
|
|
SINGLE_EVENT_JSON,
|
|
Method::Post,
|
|
Some("lz64"),
|
|
None,
|
|
"application/x-www-form-urlencoded",
|
|
StatusCode::OK,
|
|
Box::new(form_lz64_urlencoded_payload),
|
|
),
|
|
// batch payload test variants
|
|
|
|
// plain JSON POST body
|
|
TestCase::new(
|
|
"new_post-simple-batch-payload".to_string(),
|
|
DEFAULT_TEST_TIME,
|
|
CaptureMode::Events,
|
|
"",
|
|
BATCH_EVENTS_JSON,
|
|
Method::Post,
|
|
None,
|
|
None,
|
|
"application/json",
|
|
StatusCode::OK,
|
|
Box::new(plain_json_payload),
|
|
),
|
|
// plain base64'd JSON payload in POST body
|
|
TestCase::new(
|
|
"new_post-base64-batch-payload".to_string(),
|
|
DEFAULT_TEST_TIME,
|
|
CaptureMode::Events,
|
|
"",
|
|
BATCH_EVENTS_JSON,
|
|
Method::Post,
|
|
Some("base64"),
|
|
None,
|
|
"application/json",
|
|
StatusCode::OK,
|
|
Box::new(base64_payload),
|
|
),
|
|
// base64'd JSON payload w/o SDK encoding hint
|
|
TestCase::new(
|
|
"new_post-base64-no-hint-batch-payload".to_string(),
|
|
DEFAULT_TEST_TIME,
|
|
CaptureMode::Events,
|
|
"",
|
|
BATCH_EVENTS_JSON,
|
|
Method::Post,
|
|
None, // no compression hint; handling must auto-detect
|
|
None,
|
|
"text/plain",
|
|
StatusCode::OK,
|
|
Box::new(base64_payload),
|
|
),
|
|
// GZIP'd JSON single event payload
|
|
TestCase::new(
|
|
"new_post-gzip-batch-payload".to_string(),
|
|
DEFAULT_TEST_TIME,
|
|
CaptureMode::Events,
|
|
"",
|
|
BATCH_EVENTS_JSON,
|
|
Method::Post,
|
|
Some("gzip"),
|
|
None,
|
|
"application/json",
|
|
StatusCode::OK,
|
|
Box::new(gzipped_payload),
|
|
),
|
|
// GZIP'd single event JSON payload w/o SDK encoding hint
|
|
TestCase::new(
|
|
"new_post-gzip-no-hint-batch-payload".to_string(),
|
|
DEFAULT_TEST_TIME,
|
|
CaptureMode::Events,
|
|
"",
|
|
BATCH_EVENTS_JSON,
|
|
Method::Post,
|
|
None, // no compression hint; handling must auto-detect
|
|
None,
|
|
"text/plain",
|
|
StatusCode::OK,
|
|
Box::new(gzipped_payload),
|
|
),
|
|
// batched events JSON payload submitted as POST form w/base64'd "data" attribute value
|
|
TestCase::new(
|
|
"new_post-form-data-base64-batch-payload".to_string(),
|
|
DEFAULT_TEST_TIME,
|
|
CaptureMode::Events,
|
|
"",
|
|
BATCH_EVENTS_JSON,
|
|
Method::Post,
|
|
None,
|
|
None,
|
|
"application/x-www-form-urlencoded",
|
|
StatusCode::BAD_REQUEST,
|
|
Box::new(form_data_base64_payload),
|
|
),
|
|
// single event JSON payload submitted as POST form
|
|
TestCase::new(
|
|
"new_post-form-urlencoded-batch-payload".to_string(),
|
|
DEFAULT_TEST_TIME,
|
|
CaptureMode::Events,
|
|
"",
|
|
BATCH_EVENTS_JSON,
|
|
Method::Post,
|
|
None,
|
|
None,
|
|
"application/x-www-form-urlencoded",
|
|
StatusCode::OK,
|
|
Box::new(form_urlencoded_payload),
|
|
),
|
|
// single event JSON payload submitted as LZ64'd value in POST form
|
|
TestCase::new(
|
|
"new_post-form-lz64-urlencoded-batch-payload".to_string(),
|
|
DEFAULT_TEST_TIME,
|
|
CaptureMode::Events,
|
|
"",
|
|
BATCH_EVENTS_JSON,
|
|
Method::Post,
|
|
Some("lz64"),
|
|
None,
|
|
"application/x-www-form-urlencoded",
|
|
StatusCode::OK,
|
|
Box::new(form_lz64_urlencoded_payload),
|
|
),
|
|
// batch payload where one event carries heatmap-trigger properties:
|
|
// capture must produce a $$heatmap redirect alongside the originals.
|
|
TestCase::new(
|
|
"new_post-simple-batch-with-heatmap-payload".to_string(),
|
|
DEFAULT_TEST_TIME,
|
|
CaptureMode::Events,
|
|
"",
|
|
BATCH_EVENTS_WITH_HEATMAP_JSON,
|
|
Method::Post,
|
|
None,
|
|
None,
|
|
"application/json",
|
|
StatusCode::OK,
|
|
Box::new(plain_json_payload),
|
|
),
|
|
];
|
|
|
|
units
|
|
}
|
|
|
|
fn get_cases() -> Vec<TestCase> {
|
|
let units = vec![
|
|
// plain base64'd JSON payload in urlencoded "data" GET param
|
|
TestCase::new(
|
|
"new_get-base64-urlencoded-single-event-payload".to_string(),
|
|
DEFAULT_TEST_TIME,
|
|
CaptureMode::Events,
|
|
"",
|
|
SINGLE_EVENT_JSON,
|
|
Method::Get,
|
|
Some("base64"),
|
|
None,
|
|
"text/plain",
|
|
StatusCode::OK,
|
|
Box::new(base64_payload),
|
|
),
|
|
// single event JSON payload submitted in urlencoded "data" GET param
|
|
TestCase::new(
|
|
"new_get-urlencoded-event-payload".to_string(),
|
|
DEFAULT_TEST_TIME,
|
|
CaptureMode::Events,
|
|
"",
|
|
SINGLE_EVENT_JSON,
|
|
Method::Get,
|
|
None,
|
|
None,
|
|
"text/plain",
|
|
StatusCode::OK,
|
|
Box::new(plain_json_payload),
|
|
),
|
|
// single event JSON payload submitted as LZ64'd value in urlencoded "data" GET param
|
|
TestCase::new(
|
|
"new_get-lz64-urlencoded-event-payload".to_string(),
|
|
DEFAULT_TEST_TIME,
|
|
CaptureMode::Events,
|
|
"",
|
|
SINGLE_EVENT_JSON,
|
|
Method::Get,
|
|
Some("lz64"),
|
|
None,
|
|
"text/plain",
|
|
StatusCode::OK,
|
|
Box::new(lz64_payload),
|
|
),
|
|
];
|
|
|
|
units
|
|
}
|