diff --git a/build/app.zig b/build/app.zig index a32d14856..87cbd8d30 100644 --- a/build/app.zig +++ b/build/app.zig @@ -1191,6 +1191,22 @@ fn addTests( .filters = test_filters, })); } + const tour_tests = b.addTest(.{ + .name = "fizzy-tour-tests", + .root_module = b.createModule(.{ + .target = target, + .optimize = optimize, + .root_source_file = b.path("src/editor/demos/tour.zig"), + }), + .filters = test_filters, + }); + tour_tests.root_module.addImport("tape", b.createModule(.{ + .target = target, + .optimize = optimize, + .root_source_file = b.path("sdk/tape/root.zig"), + })); + try unit_test_artifacts.append(b.allocator, tour_tests); + // The backend package's std-only tests (window layout, the title-bar hit test, the blur // region, the viewport map, the health counters), from its own list, so `zig build test` // here still runs them. diff --git a/sdk/tape/Script.zig b/sdk/tape/Script.zig index 0a82b0f96..83cc4efa5 100644 --- a/sdk/tape/Script.zig +++ b/sdk/tape/Script.zig @@ -427,6 +427,21 @@ pub fn commandWith(self: *Script, id: []const u8, args: anytype) !void { const testing = std.testing; +test "a lacked name is left out of the script and an offered name stays" { + var s: Script = .init(testing.allocator, "t", "T"); + try s.keyframe(.{ .root = "demo://t" }); + try testing.expect(!s.lacksName("missing")); + s.lacks = &.{"missing"}; + for ([_][]const u8{ "missing", "offered" }) |name| { + if (s.lacksName(name)) continue; + try s.command(name); + } + var owned = try s.finish(); + defer owned.deinit(); + try testing.expectEqual(@as(usize, 3), owned.tape.ops.len); + try testing.expectEqualStrings("offered", owned.tape.ops[2].do.command.id); +} + test "a skip counts the ops pushed between it and its end" { var s: Script = .init(testing.allocator, "t", "T"); try s.keyframe(.{ .root = "demo://t" }); diff --git a/src/editor/demos/tour.zig b/src/editor/demos/tour.zig index 7dcfc7412..a6615a70c 100644 --- a/src/editor/demos/tour.zig +++ b/src/editor/demos/tour.zig @@ -138,7 +138,7 @@ pub fn build(s: *Script) !void { // Only what this OS draws: a material it lacks is left out, with its caption. const materials = [_]struct { kind: []const u8, name: []const u8, caption: ?[]const u8, ms: u32 }{ .{ .kind = "liquid", .name = "Liquid Glass", .caption = null, .ms = 1800 }, - .{ .kind = "frost", .name = "frost", .caption = "…frosted…", .ms = 1400 }, + .{ .kind = "frost", .name = "frosted glass", .caption = "…frosted…", .ms = 1400 }, .{ .kind = "blur", .name = "blur", .caption = "…blurred…", .ms = 1400 }, .{ .kind = "transparent", .name = "clear glass", .caption = "…clear, or opaque. Settings › Window keeps your choice.", .ms = 1200 }, .{ .kind = "none", .name = "opaque", .caption = null, .ms = 1200 }, @@ -199,3 +199,25 @@ pub fn build(s: *Script) !void { }); s.pause(3600); } + +test "a frost-first tour names the frosted glass it shows" { + const std = @import("std"); + var s: Script = .init(std.testing.allocator, "tour", "Tour"); + s.lacks = &.{"liquid"}; + try build(&s); + var owned = try s.finish(); + defer owned.deinit(); + const tape = owned.tape; + const chapter = for (tape.chapters) |ch| { + if (std.mem.eql(u8, ch.title, "Materials")) break ch; + } else return error.TestUnexpectedResult; + const command = for (tape.ops) |op| { + if (op.at >= chapter.at and op.do == .command) break op.do.command; + } else return error.TestUnexpectedResult; + try std.testing.expectEqualStrings("fizzy.windowMaterial", command.id); + try std.testing.expectEqualStrings(".{ .kind = \"frost\" }", command.args); + const caption = for (tape.captions) |c| { + if (c.at >= chapter.at) break c; + } else return error.TestUnexpectedResult; + try std.testing.expect(std.mem.find(u8, caption.text, "one material, frosted glass here…") != null); +}