feat(rules): 建立共享排版契约并收束 WebKit 与 Unicode 基线

This commit is contained in:
2026-09-04 21:44:11 +08:00
parent 8ee9895247
commit 993cf576c6
42 changed files with 8511 additions and 1422 deletions
+196
View File
@@ -0,0 +1,196 @@
import AppKit
import Darwin
import Foundation
import WebKit
@MainActor
final class WkWebViewHarness: NSObject, WKNavigationDelegate
{
private let app: NSApplication
private let window: NSWindow
private let webView: WKWebView
private var finished = false
init(app: NSApplication, pagePath: String, readRoot: String)
{
self.app = app
let configuration = WKWebViewConfiguration()
configuration.websiteDataStore = .nonPersistent()
webView = WKWebView(
frame: NSRect(x: 0, y: 0, width: 1224, height: 768),
configuration: configuration
)
window = NSWindow(
contentRect: webView.frame,
styleMask: [ .titled, .closable, .resizable ],
backing: .buffered,
defer: false
)
super.init()
webView.navigationDelegate = self
window.title = "Juzhen WKWebView E2E"
window.contentView = webView
window.center()
window.makeKeyAndOrderFront(nil)
let pageUrl = URL(fileURLWithPath: pagePath)
let readUrl = URL(fileURLWithPath: readRoot, isDirectory: true)
webView.loadFileURL(pageUrl, allowingReadAccessTo: readUrl)
DispatchQueue.main.asyncAfter(deadline: .now() + 20)
{ [weak self] in
self?.finish(code: 2, reason: "timeout")
}
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!)
{
evaluate("navigator.userAgent")
{ value in
print("WKWEBVIEW_USER_AGENT=\(value)")
}
click(buttonId: "run-core")
pollTitle(expectedPrefix: "CORE PASS", timeoutAt: Date().addingTimeInterval(8))
{ [weak self] coreTitle in
guard let self else { return }
guard coreTitle.hasPrefix("CORE PASS") else
{
self.collectAndFinish(code: 3, reason: "core title: \(coreTitle)")
return
}
self.click(buttonId: "run-observer")
self.pollTitle(expectedPrefix: "PASS", timeoutAt: Date().addingTimeInterval(8))
{ [weak self] finalTitle in
guard let self else { return }
let success = finalTitle.hasPrefix("PASS")
self.collectAndFinish(
code: success ? 0 : 4,
reason: "final title: \(finalTitle)"
)
}
}
}
func webView(
_ webView: WKWebView,
didFail navigation: WKNavigation!,
withError error: Error
)
{
finish(code: 5, reason: "navigation failed: \(error)")
}
func webView(
_ webView: WKWebView,
didFailProvisionalNavigation navigation: WKNavigation!,
withError error: Error
)
{
finish(code: 6, reason: "provisional navigation failed: \(error)")
}
private func click(buttonId: String)
{
let script = "document.getElementById('\(buttonId)')?.click(); document.title;"
evaluate(script)
{ value in
print("WKWEBVIEW_CLICK_\(buttonId)=\(value)")
}
}
private func pollTitle(
expectedPrefix: String,
timeoutAt: Date,
completion: @escaping (String) -> Void
)
{
evaluate("document.title")
{ [weak self] value in
guard let self else { return }
if value.hasPrefix(expectedPrefix) || value.hasPrefix("FAIL") || Date() >= timeoutAt
{
completion(value)
return
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1)
{ [weak self] in
self?.pollTitle(
expectedPrefix: expectedPrefix,
timeoutAt: timeoutAt,
completion: completion
)
}
}
}
private func collectAndFinish(code: Int32, reason: String)
{
let script = """
JSON.stringify({
title: document.title,
summary: document.getElementById('summary-text')?.textContent || '',
failures: Array.from(document.querySelectorAll('#results li[data-state="fail"]'))
.map((item) => item.textContent),
results: Array.from(document.querySelectorAll('#results li'))
.map((item) => item.textContent)
})
"""
evaluate(script)
{ [weak self] value in
print("WKWEBVIEW_RESULT=\(value)")
self?.finish(code: code, reason: reason)
}
}
private func evaluate(_ script: String, completion: @escaping (String) -> Void)
{
webView.evaluateJavaScript(script)
{ value, error in
if let error
{
completion("EVALUATION_ERROR: \(error)")
return
}
completion(String(describing: value ?? "nil"))
}
}
private func finish(code: Int32, reason: String)
{
guard !finished else { return }
finished = true
print("WKWEBVIEW_EXIT_REASON=\(reason)")
fflush(stdout)
window.close()
app.stop(nil)
exit(code)
}
}
@main
struct Main
{
@MainActor
private static var harness: WkWebViewHarness?
@MainActor
static func main()
{
guard CommandLine.arguments.count == 3 else
{
fputs("usage: harness <e2e.html> <read-root>\n", stderr)
exit(64)
}
let app = NSApplication.shared
app.setActivationPolicy(.accessory)
harness = WkWebViewHarness(
app: app,
pagePath: CommandLine.arguments[1],
readRoot: CommandLine.arguments[2]
)
app.run()
}
}