#[test] fn runtime_posts_urlencoded_forms_by_default() { let source = slhx_js::RUNTIME_JS; assert!(source.contains("new URLSearchParams()")); assert!(source.contains("multipart/form-data")); assert!(source.contains("const body = method === \"GET\" || method === \"HEAD\" ? undefined : requestBody(data, multipart)")); assert!(source.contains("application/x-www-form-urlencoded;charset=UTF-8")); } #[test] fn runtime_handles_get_forms_without_request_body() { let source = slhx_js::RUNTIME_JS; assert!(source.contains("function requestUrl(form, data, method)")); assert!(source.contains("method === \"GET\" || method === \"HEAD\" ? undefined : requestBody")); assert!(source.contains("if (method === \"GET\") url.search = urlEncoded(data).toString()")); } #[test] fn runtime_clicking_submitter_schedules_form_submit() { // req: convention/004 let source = slhx_js::RUNTIME_JS; assert!(source.contains("function formOwner(el)")); assert!(source.contains("function formHandleId(form)")); assert!(source.contains("document.getElementById(el.getAttribute(\"form\"))")); assert!(source.contains("const direct = closestInRoot(event.target, root, `[${HID}]`)")); assert!(source.contains("button[type=submit], input[type=submit], button:not([type])")); assert!(source.contains("form.reportValidity && !form.reportValidity()")); assert!(source.contains("schedule(form, \"submit\")")); } #[test] fn runtime_supports_drag_drop_params_without_user_js() { // req: htmx_equivalents/002, req: dx/008 let source = slhx_js::RUNTIME_JS; assert!(source.contains("const dragKeys = new WeakMap()")); assert!(source.contains("dragstart")); assert!(source.contains("dragover")); assert!(source.contains("eventName === \"drop\"")); assert!(source.contains("data.set(\"work_id\", dragKey)")); } #[test] fn runtime_supports_queued_request_policy() { let source = slhx_js::RUNTIME_JS; assert!(source.contains("const queues = new WeakMap()")); assert!(source.contains("policy === \"queue\"")); assert!(source.contains("const base = queues.get(target) || active.done")); } #[test] fn runtime_exposes_page_swap_hooks() { let source = slhx_js::RUNTIME_JS; assert!(source.contains("data-slhx-nav")); assert!(source.contains("data-slhx-boost")); assert!(source.contains("history.pushState")); assert!(source.contains("popstate")); assert!(source.contains("x-slhx-title")); assert!(source.contains("x-slhx-fingerprint")); assert!(source.contains("slhx:missing-content-slot")); assert!(source.contains("location.href = href")); } #[test] fn runtime_page_swaps_lowered_slot_ids() { // req: wire/001 let source = slhx_js::RUNTIME_JS; assert!(source.contains("function replaceLoweredSlots(scope, doc)")); assert!(source.contains("doc.querySelectorAll(\"[data-sid], [data-slot-id]\")")); assert!(source.contains("target.innerHTML = source.innerHTML")); } #[test] fn runtime_keeps_form_field_targets_separate_from_error_targets() { let source = slhx_js::RUNTIME_JS; assert!(source.contains("function fieldTarget(scope, id, field)")); assert!(source.contains("[data-fid=\"${id}\"] [name=\"${escapedField}\"]")); assert!(source.contains("function formErrorTarget(scope, id, field)")); assert!(source.contains("[data-slhx-error-for=\"${escapedField}\"]")); } #[test] fn runtime_preflights_batches_before_applying_ops() { let source = slhx_js::RUNTIME_JS; assert!(source.contains("const missingTarget = batch.ops.map((op) => canApplyOp(scope, op)).find(Boolean)")); assert!(source.contains("function canApplyOp(scope, op)")); assert!(source.contains("for (const op of batch.ops) applyOp(scope, op)")); } #[test] fn runtime_ships_typescript_definitions() { let source = slhx_js::RUNTIME_D_TS; assert!(source.contains("req: ts/001")); assert!(source.contains("export interface EffectBatch")); assert!(source.contains("fingerprint: bigint")); assert!(source.contains("export type Effect =")); assert!(source.contains("decodeBatch(buffer: ArrayBuffer): EffectBatch")); assert!(source.contains("interface Window")); }