spec/cli_cgi_spec.cr @ trunk
spec
scale = 0.75 fontscale = 1.500 box wid 1.380 ht 0.340 with .nw at (0.035, -0.035) fill 0xCBD5E1 color 0xCBD5E1 box wid 1.380 ht 0.340 with .nw at (0.000, 0.000) fill 0x7C83E6 color 0x7C83E6 box wid 0.300 ht 0.065 rad 0.018 at (0.370, -0.022) fill 0xffffff color 0xffffff line from (0.140, 0.000) to (0.140, -0.340) color white line from (1.240, 0.000) to (1.240, -0.340) color white text "require 'spec'" color white at (0.690, -0.170)→ /pikchrshow
crystal source
require "spec"
json block
{
"kind": "require",
"name": "spec",
"doc": null,
"children": []
}
private def fossil_checkout_hash : String?
buf = IO::Memory.new
status = Process.run("fossil", ["info"], output: buf, error: Process::Redirect::Close)
return nil unless status.success?
line = buf.to_s.lines.find(&.starts_with?("checkout:"))
line.try { |l| l.split(/\s+/)[1]? }
end
private def gpcr_bin : String
File.join(Dir.current, "bin", "gpcr")
end
describe "gpcr render with reflected faces" do
bin = gpcr_bin
unless File.exists?(bin)
pending "gpcr binary not present — skipping render-with-faces tests"
next
end
it "renders on_start as 'on start' (hat label filled, not raw def name)" do
buf = IO::Memory.new
Process.run(bin, ["render", "examples/blink.cr"], output: buf, error: Process::Redirect::Close)
buf.to_s.should contain("on start")
end
it "renders set_user_led with its slot as a filled input pill" do
buf = IO::Memory.new
Process.run(bin, ["render", "examples/blink.cr"], output: buf, error: Process::Redirect::Close)
md = buf.to_s
md.should contain(%(text "set user LED " color white))
md.should contain(%(text "true" color 0x263238))
end
it "renders wait with its numeric slot as a filled input pill" do
buf = IO::Memory.new
Process.run(bin, ["render", "examples/blink.cr"], output: buf, error: Process::Redirect::Close)
md = buf.to_s
md.should contain(%(text "wait " color white))
md.should contain(%(text "0.5" color 0x263238))
md.should contain(%(text " seconds" color white))
end
end
describe "gpcr render gallery.cr" do
bin = gpcr_bin
unless File.exists?(bin)
pending "gpcr binary not present — skipping gallery render tests"
next
end
it "renders all gallery shape labels" do
buf = IO::Memory.new
Process.run(bin, ["render", "src/gpcr/gallery.cr"], output: buf, error: Process::Redirect::Close)
out = buf.to_s
["hat shape", "command shape", "reporter shape", "boolean shape",
"predefined process shape", "document shape", "stop script", "ring shape"].each do |label|
out.should contain(label)
end
end
it "renders all structure node kinds in the gallery_structures graph" do
buf = IO::Memory.new
Process.run(bin, ["render", "src/gpcr/gallery.cr"], output: buf, error: Process::Redirect::Close)
out = buf.to_s
out.should contain(%(text "if " color white))
out.should contain(%(text "while " color white))
out.should contain(%(text "match " color white))
out.should contain(%(text "gallery_boolean" color 0x263238))
out.should contain(%(text "gallery_reporter" color 0x263238))
out.should contain("forever")
end
end
# Ticket ca825f45f6: the design gallery capstone requires BOTH visual token
# styles to be reachable on the live page, not just that render_source CAN
# take a token_set argument. These run the compiled binary through the real
# CGI dispatch path (PATH_INFO=gallery, QUERY_STRING=tokens=...) exactly as
# Fossil's CGI would invoke it — no real fossil repo needed, since the
# gallery branch never reads FOSSIL_REPOSITORY beyond checking it's set.
private def run_gallery_cgi(bin : String, query : String) : String
buf = IO::Memory.new
scrubbed_env = {
"PATH" => "/usr/bin:/bin",
"GATEWAY_INTERFACE" => "CGI/1.1",
"REQUEST_METHOD" => "GET",
"PATH_INFO" => "gallery",
"QUERY_STRING" => query,
"SCRIPT_NAME" => "/x/ext/gpcr",
"FOSSIL_REPOSITORY" => "unused-but-must-be-set",
"FOSSIL_CAPABILITIES" => "oh",
}
Process.run(bin, env: scrubbed_env, clear_env: true, output: buf, error: Process::Redirect::Close)
buf.to_s
end
describe "gpcr CGI gallery route: both design token sets" do
bin = gpcr_bin
unless File.exists?(bin)
pending "gpcr binary not present — skipping gallery token-set CGI tests"
next
end
it "defaults to microblocks-compact (fontscale 1.500) with no tokens= param" do
body = run_gallery_cgi(bin, "")
body.should contain("fontscale = 1.500")
body.should_not contain("fontscale = 2.000")
body.should contain("Design Gallery (microblocks-compact")
body.should contain("[view blockly-zelos](/ext/gpcr/gallery?tokens=blockly-zelos)")
end
it "renders blockly-zelos (fontscale 2.000, different geometry) when asked" do
body = run_gallery_cgi(bin, "tokens=blockly-zelos")
body.should contain("fontscale = 2.000")
body.should_not contain("fontscale = 1.500")
body.should contain("Design Gallery (blockly-zelos")
body.should contain("[view microblocks-compact](/ext/gpcr/gallery?tokens=microblocks-compact)")
end
it "renders every gallery shape under blockly-zelos too, not just the default set" do
body = run_gallery_cgi(bin, "tokens=blockly-zelos")
["hat shape", "command shape", "reporter shape", "boolean shape",
"predefined process shape", "document shape", "stop script", "ring shape"].each do |label|
body.should contain(label)
end
end
end
describe "gpcr CGI explorer default_ci" do
bin = gpcr_bin
fossil_repo = "/var/lib/fossil/gp-crystal.fossil"
unless File.exists?(bin) && File.exists?(fossil_repo)
pending "gpcr binary or fossil repo not present — skipping CGI env smoke test"
next
end
expected_hash = fossil_checkout_hash
unless expected_hash
pending "not inside a fossil checkout — cannot verify default_ci hash"
next
end
it "shows the checkout hash (not trunk) when HOME is absent from the CGI environment" do
buf = IO::Memory.new
# Simulate the CGI environment that the preview dispatcher creates:
# PATH-only env, no HOME, no FOSSIL_HOME — the binary must set those itself.
scrubbed_env = {
"PATH" => "/usr/bin:/bin",
"GATEWAY_INTERFACE" => "CGI/1.1",
"REQUEST_METHOD" => "GET",
"PATH_INFO" => "",
"QUERY_STRING" => "",
"SCRIPT_NAME" => "/x/ext/preview/id/test",
"FOSSIL_REPOSITORY" => fossil_repo,
"FOSSIL_CAPABILITIES" => "o",
}
status = Process.run(bin, env: scrubbed_env, clear_env: true, output: buf, error: Process::Redirect::Close)
status.success?.should be_true
body = buf.to_s
body.should contain("Revision: `#{expected_hash}`")
body.should_not contain("Revision: `trunk`")
end
it "shows census metrics (gpcr_pct and block/primitive counts) on the main page" do
buf = IO::Memory.new
scrubbed_env = {
"PATH" => "/usr/bin:/bin",
"GATEWAY_INTERFACE" => "CGI/1.1",
"REQUEST_METHOD" => "GET",
"PATH_INFO" => "",
"QUERY_STRING" => "",
"SCRIPT_NAME" => "/x/ext/preview/id/test",
"FOSSIL_REPOSITORY" => fossil_repo,
"FOSSIL_CAPABILITIES" => "o",
}
Process.run(bin, env: scrubbed_env, clear_env: true, output: buf, error: Process::Redirect::Close)
body = buf.to_s
body.should contain("**Census:**")
body.should contain("% GPCR")
body.should contain("blocks:")
body.should contain("primitives:")
end
end
# Ticket 57a83fc3c0: the Fossil skin's persistent nav menu links to the gpcr
# explorer. It must NOT hardcode ?ci=trunk — that overrides default_ci's
# correct per-checkout resolution (ticket 23d80447dc) and defeats "works the
# same way for any checkin being browsed." This only checks the TRACKED file
# fossil-skin/mainmenu; the live Fossil "mainmenu" setting is applied
# separately by an admin action outside source control and isn't re-checked
# here.
describe "fossil-skin/mainmenu: GPCR entry" do
it "links to the explorer without overriding the checkin with ?ci=trunk" do
content = File.read(File.join(__DIR__, "..", "fossil-skin", "mainmenu"))
gpcr_line = content.lines.find(&.starts_with?("GPCR "))
gpcr_line.should_not be_nil
gpcr_line.not_nil!.should contain("/ext/gpcr/")
gpcr_line.not_nil!.should_not contain("?ci=trunk")
end
end