code wiki / (root) / nx_dom_click.nx

nx_dom_click.nx source

↩ module page · 145 lines · 5866 B

1// nx_dom_click.nx -- bits-up "click intent" extractor. Locates an 2// element by selector criteria and extracts its (action_id, arg0..arg3) 3// tuple from the data-action / data-arg0..3 attributes. The test 4// driver then passes those values to the game's nx_*_action() function 5// to simulate the click. 6// 7// Composes nx_dom_query.nx (locates the element). Single-exit pattern 8// to sidestep the parser scope quirk noted in 9// [[project-bits-up-test-driver-roadmap-2026-05-20]]. 10 11import "nx_dom_query.nx" 12 13struct NxClickIntent { 14 found: i64, // 1 if matching element exists AND has data-action 15 action: i64, // value of data-action (integer) 16 arg0: i64, // value of data-arg0 (or 0 if absent) 17 arg1: i64, // value of data-arg1 (or 0 if absent) 18 arg2: i64, // value of data-arg2 (or 0 if absent) 19 arg3: i64 // value of data-arg3 (or 0 if absent) 20} 21 22func _ck_strlen(s: *u8) -> i64 { 23 var n: i64 = 0 24 while s[n] != 0 { n = n + 1 } 25 return n 26} 27 28// Parse a decimal integer (signed via leading '-') from a byte range. 29// Returns the value via out_val; returns 1 on success, 0 on parse error. 30func _ck_parse_int(src: *u8, off: i64, len: i64, out_val: *i64) -> i64 { 31 if len <= 0 { return 0 } 32 var i: i64 = 0 33 var sign: i64 = 1 34 if src[off] == 45 { // '-' 35 sign = -1 36 i = 1 37 } 38 if i >= len { return 0 } 39 var acc: i64 = 0 40 while i < len { 41 let b: i64 = src[off + i] as i64 42 if b < 48 { return 0 } 43 if b > 57 { return 0 } 44 acc = acc * 10 + (b - 48) 45 i = i + 1 46 } 47 out_val[0] = acc * sign 48 return 1 49} 50 51// Extract a data-attr's integer value from a START_TAG slice. If the 52// attr is missing OR present-but-non-numeric, returns the supplied 53// default. 54func nx_dom_attr_int_at(html: *u8, tag_off: i64, tag_len: i64, 55 attr_name: *u8, default_val: i64) -> i64 { 56 let val_off: *i64 = sys_mmap(8) as *i64 57 let val_len: *i64 = sys_mmap(8) as *i64 58 let has: i64 = nx_dom_find_attr(html, tag_off, tag_len, 59 attr_name, val_off, val_len) 60 if has != 1 { return default_val } 61 let parsed: *i64 = sys_mmap(8) as *i64 62 let ok: i64 = _ck_parse_int(html, val_off[0], val_len[0], parsed) 63 if ok != 1 { return default_val } 64 return parsed[0] 65} 66 67// Locate an element by (attr_name == attr_value) and extract its click 68// intent. Single entry point the test driver uses for "click N-th sq" 69// or "click button with data-action=2". 70func nx_dom_click_intent(html: *u8, html_len: i64, 71 attr_name: *u8, attr_value: *u8) -> *NxClickIntent { 72 let intent: *NxClickIntent = sys_mmap(48) as *NxClickIntent 73 intent.found = 0 74 intent.action = 0 75 intent.arg0 = 0 76 intent.arg1 = 0 77 intent.arg2 = 0 78 intent.arg3 = 0 79 80 let r: *NxDomQueryResult = nx_dom_find_attr_eq(html, html_len, 81 attr_name, attr_value) 82 if r.found != 1 { return intent } 83 84 // The element must have data-action to be clickable. 85 let val_off: *i64 = sys_mmap(8) as *i64 86 let val_len: *i64 = sys_mmap(8) as *i64 87 let action_attr: *u8 = "data-action" as *u8 88 let has_action: i64 = nx_dom_find_attr(html, r.tag_off, r.tag_len, 89 action_attr, val_off, val_len) 90 if has_action != 1 { return intent } 91 let parsed: *i64 = sys_mmap(8) as *i64 92 let ok: i64 = _ck_parse_int(html, val_off[0], val_len[0], parsed) 93 if ok != 1 { return intent } 94 95 intent.found = 1 96 intent.action = parsed[0] 97 intent.arg0 = nx_dom_attr_int_at(html, r.tag_off, r.tag_len, 98 "data-arg0" as *u8, 0 as i64) 99 intent.arg1 = nx_dom_attr_int_at(html, r.tag_off, r.tag_len, 100 "data-arg1" as *u8, 0 as i64) 101 intent.arg2 = nx_dom_attr_int_at(html, r.tag_off, r.tag_len, 102 "data-arg2" as *u8, 0 as i64) 103 intent.arg3 = nx_dom_attr_int_at(html, r.tag_off, r.tag_len, 104 "data-arg3" as *u8, 0 as i64) 105 return intent 106} 107 108// Variant: locate first element with class==class_name (word-boundary) 109// and extract its click intent. Useful for "click the first reset button" 110// when there's only one element of that class. 111func nx_dom_click_intent_by_class(html: *u8, html_len: i64, 112 class_name: *u8) -> *NxClickIntent { 113 let intent: *NxClickIntent = sys_mmap(48) as *NxClickIntent 114 intent.found = 0 115 intent.action = 0 116 intent.arg0 = 0 117 intent.arg1 = 0 118 intent.arg2 = 0 119 intent.arg3 = 0 120 121 let r: *NxDomQueryResult = nx_dom_find_class(html, html_len, class_name) 122 if r.found != 1 { return intent } 123 124 let val_off: *i64 = sys_mmap(8) as *i64 125 let val_len: *i64 = sys_mmap(8) as *i64 126 let action_attr: *u8 = "data-action" as *u8 127 let has_action: i64 = nx_dom_find_attr(html, r.tag_off, r.tag_len, 128 action_attr, val_off, val_len) 129 if has_action != 1 { return intent } 130 let parsed: *i64 = sys_mmap(8) as *i64 131 let ok: i64 = _ck_parse_int(html, val_off[0], val_len[0], parsed) 132 if ok != 1 { return intent } 133 134 intent.found = 1 135 intent.action = parsed[0] 136 intent.arg0 = nx_dom_attr_int_at(html, r.tag_off, r.tag_len, 137 "data-arg0" as *u8, 0 as i64) 138 intent.arg1 = nx_dom_attr_int_at(html, r.tag_off, r.tag_len, 139 "data-arg1" as *u8, 0 as i64) 140 intent.arg2 = nx_dom_attr_int_at(html, r.tag_off, r.tag_len, 141 "data-arg2" as *u8, 0 as i64) 142 intent.arg3 = nx_dom_attr_int_at(html, r.tag_off, r.tag_len, 143 "data-arg3" as *u8, 0 as i64) 144 return intent 145}