1+ # 用嵌入式 V8 (py_mini_racer) 执行 hic.js,并对结果做断言
2+ import sys , io , json
3+ from py_mini_racer import MiniRacer
4+
5+ with io .open (r"D:\hicode-ide\js\hic.js" , "r" , encoding = "utf-8" ) as f :
6+ hic_src = f .read ()
7+
8+ # 兼容 node 的 module.exports:py_mini_racer 无 module/window。
9+ # 我们用无头 IIFE 风格:hic.js 里 `if (typeof module... ) module.exports`;此处模拟 module。
10+ js_test = r"""
11+ var __out = {};
12+ var module = { exports: {} };
13+ var _result = null;
14+ """ + hic_src + r"""
15+ var HC = module.exports;
16+
17+ var pass = 0, fail = 0, logs = [];
18+ function ok(cond, label){ if(cond){pass++;} else {fail++; logs.push("F "+label);} }
19+
20+ // 1. 变量声明
21+ var r = HC.classify("it title t 你好 HiCode");
22+ ok(r.kind==="it" && r.name==="title" && r.vtype==="text" && r.value==="你好 HiCode", "it title t");
23+ r = HC.classify("it logo p");
24+ ok(r.kind==="it" && r.name==="logo" && r.vtype==="img" && r.value==="", "it logo p");
25+ r = HC.classify("it age int 18");
26+ ok(r.kind==="it" && r.name==="age" && r.vtype==="ordinary", "it age int ordinary");
27+ r = HC.classify("it msg");
28+ ok(r.kind==="it" && r.name==="msg" && r.vtype==="ordinary", "it msg ordinary");
29+
30+ // 2. in 展示
31+ r = HC.classify("title in t");
32+ ok(r.kind==="in" && r.mode==="text", "in t");
33+ r = HC.classify("logo in p");
34+ ok(r.kind==="in" && r.mode==="img", "in p");
35+
36+ // 3. 条件头
37+ ok(HC.classify("if age == 18:").type==="if", "if头");
38+ ok(HC.classify("orif age > 18:").type==="orif", "orif头");
39+ ok(HC.classify("noif:").type==="noif", "noif头");
40+
41+ // 4. 表达式求值
42+ ok(HC.evalExpr("age == 18", {age:{value:18}})===true, "数值比较");
43+ ok(HC.evalExpr("1 == 1 and 2 > 1", {})===true, "and");
44+ ok(HC.evalExpr("1 > 2 or 3 == 3", {})===true, "or");
45+ ok(HC.evalExpr("not (1 == 2)", {})===true, "not");
46+ ok(HC.evalExpr("'hello' in 'xxhello'", {})===true, "in子串");
47+
48+ // 5. 导向
49+ r = HC.parseNav("home to about");
50+ ok(r && !r.cross && r.toPage==="about", "同项目 x to y");
51+ r = HC.parseNav("to about");
52+ ok(r && !r.cross && r.toPage==="about", "to y");
53+ r = HC.parseNav("fr 我的项目 首页 big to 我的项目 关于");
54+ ok(r && r.cross && r.toProj==="我的项目", "fr 项目 页面 big to");
55+
56+ // 6. 端到端
57+ var page = { name:"index", code: [
58+ "it title t 你好,HiCode",
59+ "it intro t 简单上手的编程语言",
60+ "it logo p",
61+ "it count int 3",
62+ "if count == 3:",
63+ " intro in t",
64+ "noif:",
65+ " title in t",
66+ "to about"
67+ ].join("\n"), images: { logo: "data:image/png;base64,AAAA" } };
68+ var pr = HC.processPage(page, {});
69+ ok(Object.keys(pr.vars).length===4, "4变量");
70+ ok(pr.vars.logo.isImg && pr.vars.logo.value==="data:image/png;base64,AAAA", "p绑定图片");
71+ var ts = pr.items.filter(function(x){return x.kind==="display" && x.mode==="text";});
72+ ok(ts.length===1 && ts[0].value==="简单上手的编程语言", "if命中intro");
73+ ok(pr.items.filter(function(x){return x.kind==="nav";}).length===1, "1导向");
74+
75+ // 7. HTML
76+ var proj = { id:"p1", name:"我的项目", pages:{
77+ p_a:page, p_b:{ id:"p_b", name:"about", code:"it hello t 关于我们\nhello in t", images:{} } } };
78+ var merged = HC.buildProjectMergedHtml(proj, {});
79+ ok(merged.indexOf('data-page="我的项目::index"')>=0, "合并含index");
80+ ok(merged.indexOf("简单上手的编程语言")>=0, "合并含文本");
81+ ok(/<!DOCTYPE html>/i.test(merged), "HTML骨架");
82+ var single = HC.buildSinglePageHtml({name:"我的项目"}, page);
83+ ok(single.indexOf("简单上手")>=0 || single.indexOf("你好,HiCode")>=0, "单页html");
84+
85+ // 8. ZIP
86+ var entries = HC.buildZipEntries([proj]);
87+ ok(entries.length===2, "zip两页");
88+ var z = HC.zipFiles(entries.map(function(e){return {name:e.name, data:e.html};}));
89+ ok(z && z[0]===0x50 && z[1]===0x4b, "zip魔数PK");
90+
91+ __out = { pass: pass, fail: fail, logs: logs.slice(0,20) };
92+ JSON.stringify(__out);
93+ """
94+
95+ res_json = MiniRacer ().eval (js_test )
96+ r = json .loads (res_json )
97+ print ("通过:" , r ["pass" ], "失败:" , r ["fail" ])
98+ print ("RESULT_JSON:" , json .dumps (r , ensure_ascii = False ))
99+ for l in r ["logs" ]:
100+ print (" " , l )
101+ sys .exit (1 if r ["fail" ] else 0 )
0 commit comments