nx_uxcx_grade_test.nx source
↩ module page · 70 lines · 4100 B
1// nx_uxcx_grade_test.nx -- sovereign gate for the UX/CX grader.
2//
3// Proves the byte-scan detectors catch the two operator-reported bug classes
4// (browser-only back nav; & double-encoding) and pass clean input, and
5// that the combined permil moves. Same verdicts as the nishilib.uxcx Python
6// benchmark on the same fixtures. Exit code = failed assertion #; 0 = all pass.
7
8import "nx_syscalls.nx"
9import "nx_uxcx_grade.nx"
10
11func main() -> i64 {
12 // buggy JS: back button wired inline to history.back(), no fallback
13 let js_bug: *u8 = "$(\"back\").addEventListener(\"click\", () => history.back());" as *u8
14 // fixed JS: named goBack() with an in-app fallback
15 let js_fix: *u8 = "function goBack(){ if (userNavigated) history.back(); else location.hash=lastListHash; }" as *u8
16 // double-encoded title (the & bug as the reader sees it)
17 let html_bad: *u8 = "<div class=\"title\">Cats &amp; Dogs &lt;i&gt;</div>" as *u8
18 // correctly single-encoded title
19 let html_ok: *u8 = "<div class=\"title\">Cats & Dogs</div>" as *u8
20 // a page with viewport + skip-link
21 let page_ok: *u8 = "<meta name=\"viewport\" content=\"width=device-width\"><a class=\"skip-link\" href=\"#m\">skip</a>" as *u8
22 // a page missing both
23 let page_bad: *u8 = "<head><title>x</title></head>" as *u8
24
25 // back-nav (operator bug #1)
26 if uxg_back_ok(js_bug, uxg_len(js_bug)) != 0 { return 1 }
27 if uxg_back_ok(js_fix, uxg_len(js_fix)) != 1 { return 2 }
28 // escaping / & (operator bug #2)
29 if uxg_escaping_ok(html_bad, uxg_len(html_bad)) != 0 { return 3 }
30 if uxg_escaping_ok(html_ok, uxg_len(html_ok)) != 1 { return 4 }
31 // mobile viewport
32 if uxg_viewport_ok(page_ok, uxg_len(page_ok)) != 1 { return 5 }
33 if uxg_viewport_ok(page_bad, uxg_len(page_bad)) != 0 { return 6 }
34 // skip link
35 if uxg_skiplink_ok(page_ok, uxg_len(page_ok)) != 1 { return 7 }
36 if uxg_skiplink_ok(page_bad, uxg_len(page_bad)) != 0 { return 8 }
37
38 // combined permil: clean page+fixed-js = 1000, buggy page+buggy-js = 250
39 if uxg_permil(page_ok, uxg_len(page_ok), js_fix, uxg_len(js_fix)) != 1000 { return 9 }
40 if uxg_permil(page_bad, uxg_len(page_bad), js_bug, uxg_len(js_bug)) != 250 { return 10 }
41
42 // ---- expanded dimension checks ----
43 let page_full: *u8 = "<html lang=\"en\"><head><title>X</title><meta name=\"viewport\" content=\"width=device-width\"></head><body><nav></nav><a class=\"skip-link\" href=\"#m\">skip</a></body></html>" as *u8
44 let page_ext: *u8 = "<script src=\"https://cdn.example.com/x.js\"></script>" as *u8
45 let js_full: *u8 = "out.innerHTML='loading'; try{x}catch(e){ out.innerHTML='failed'; } if(!r){ out.innerHTML='no matches'; } function goBack(){}" as *u8
46 let js_bare: *u8 = "doStuff();" as *u8
47
48 if uxg_lang_ok(page_full, uxg_len(page_full)) != 1 { return 11 }
49 if uxg_lang_ok(page_bad, uxg_len(page_bad)) != 0 { return 12 }
50 if uxg_title_ok(page_full, uxg_len(page_full)) != 1 { return 13 }
51 if uxg_nav_ok(page_full, uxg_len(page_full)) != 1 { return 14 }
52 if uxg_sovereign_ok(page_full, uxg_len(page_full)) != 1 { return 15 }
53 if uxg_sovereign_ok(page_ext, uxg_len(page_ext)) != 0 { return 16 }
54 if uxg_loading_ok(js_full, uxg_len(js_full)) != 1 { return 17 }
55 if uxg_loading_ok(js_bare, uxg_len(js_bare)) != 0 { return 18 }
56 if uxg_error_ok(js_full, uxg_len(js_full)) != 1 { return 19 }
57 if uxg_error_ok(js_bare, uxg_len(js_bare)) != 0 { return 20 }
58 if uxg_empty_ok(js_full, uxg_len(js_full)) != 1 { return 21 }
59 if uxg_empty_ok(js_bare, uxg_len(js_bare)) != 0 { return 22 }
60
61 // full 11-check grade: clean = 1000, and degraded < clean (monotonic)
62 let g_hi: i64 = uxg_grade_full(page_full, uxg_len(page_full), js_full, uxg_len(js_full))
63 let g_lo: i64 = uxg_grade_full(page_bad, uxg_len(page_bad), js_bare, uxg_len(js_bare))
64 if g_hi != 1000 { return 23 }
65 if g_lo >= g_hi { return 24 }
66
67 let msg: *u8 = "nx_uxcx_grade: 24/24 sovereign assertions PASS (native, hardware-up)\n" as *u8
68 sys_write(1, msg, uxg_len(msg))
69 return 0
70}