Skip to content

test(fixtures): introduce zspec Factory pattern for ProjectConfig + ResourceDef#121

Merged
apotema merged 3 commits into
mainfrom
feat/zspec-factory-pov
May 15, 2026
Merged

test(fixtures): introduce zspec Factory pattern for ProjectConfig + ResourceDef#121
apotema merged 3 commits into
mainfrom
feat/zspec-factory-pov

Conversation

@apotema

@apotema apotema commented May 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Why factories

project_settings_edit_save (one of the 5 long-silent-passing tests #120 will triage) needs a populated ProjectConfig built per-test. Today's tests either run on defaults or hand-build the struct with arena.dupe per string field. Factories collapse that to Factory.build(.{ ...overrides }) with comptime field-name validation. This PR proves the pattern on existing tests before #120 starts.

Findings worth carrying forward

Test plan

  • zig build test — 175/175 pass (was 174 on v0.9.2 baseline; +1 for the new factory-override round-trip test).
  • zig build gui-test-build succeeds locally after the nfd-import restore.
  • CI: full matrix on Linux + macOS.

…esourceDef

Bumps zspec to v0.9.2 — picks up the `.simple`-runner io_instance init
fix shipped this session (apotema/zspec#45) — and lands a small
proof-of-value slice for zspec's `Factory` module before tackling #120's
TE-test triage and #109's Game View TE coverage.

Why factories now: `project_settings_edit_save` (one of the 5 long-
silent-passing tests #120 will triage) needs a populated ProjectConfig
built per-test. Today's tests either run on defaults or hand-build the
struct with arena.dupe per string field. Factories collapse that to
`Factory.build(.{ ...overrides })` and validate field names at comptime.

What changed:

- `src/test_fixtures.zig` + `src/test_fixtures/resource.zon`: two
  factories, one via `Factory.defineFrom` (leaf type — `ResourceDef`,
  fixture in a .zon file with field-name typo detection) and one via
  `Factory.define` (outer type — `ProjectConfig`, in-Zig literal so the
  `resources: []const ResourceDef = &.{}` slice field can be expressed
  as `@as([]const ResourceDef, &.{})`. `defineFrom` can't coerce empty
  slices from .zon syntax; the module doc-comment captures this).

- `src/tests.zig`: converts `resources round-trip through save + load`
  to build its `ResourceDef` via `ResourceFactory.build(.{})`, dropping
  the manual `arena.dupe` per field. Adds a sibling
  `ProjectConfigFactory overrides round-trip through save + load` that
  builds a 7-field-override config, round-trips through save/load,
  asserts every override survived and untouched fields kept their
  fixture defaults — direct precursor to #120's
  `project_settings_edit_save` shape.

- `build.zig.zon`: zspec v0.9.1 → v0.9.2.

Test plan: `zig build test` — 175/175 pass (was 174 on v0.9.2 baseline,
+1 for the new factory-override round-trip test).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@cursor

cursor Bot commented May 15, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Low risk: changes are confined to test fixtures/tests and a build-script import fix; no production runtime logic is modified. Main risk is CI/build breakage if Zig package/versioning or module imports are misconfigured.

Overview
Introduces shared test fixtures via zspec.Factory: ResourceDef defaults are sourced from a new test_fixtures/resource.zon, while ProjectConfig defaults live in Zig to handle slice fields.

Updates project file tests to build resources/configs via these factories (removing manual arena string duplication) and adds a new save/load round-trip test asserting factory overrides persist and non-overridden defaults remain.

Bumps zspec to v0.9.2 and restores gui-tests' nfd import in build.zig to fix compilation when UI code paths are analyzed.

Reviewed by Cursor Bugbot for commit df4b631. Bugbot is set up for automated code reviews on this repo. Configure here.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the zspec dependency to version 0.9.2 and introduces a factory pattern for test fixtures to centralize default data and simplify test setup. It includes new fixture definitions and refactors existing tests to use these factories, ensuring better maintenance and reduced boilerplate. The reviewer suggested updating the version prefix in the zspec hash for consistency.

Comment thread build.zig.zon
.url = "https://github.com/apotema/zspec/archive/v0.9.1.tar.gz",
.hash = "zspec-0.9.1-jaKLbbX4AwBKANdetxzzWc3UTO0UY0lcJJzTagQHlt5K",
.url = "https://github.com/apotema/zspec/archive/v0.9.2.tar.gz",
.hash = "zspec-0.9.1-jaKLbXgMBACFwbNjflhbMyP113leoYjboxn-1UOP-FGw",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The hash prefix for zspec still references version 0.9.1 while the URL has been updated to v0.9.2. While Zig's package manager primarily uses the multihash suffix for integrity, having a version mismatch in the hash string is inconsistent and can be confusing for maintenance. It is recommended to update the prefix to match the new version.

            .hash = "zspec-0.9.2-jaKLbXgMBACFwbNjflhbMyP113leoYjboxn-1UOP-FGw",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reply: tried this — Zig 0.16's package manager rejects the edit with hash mismatch: manifest declares zspec-0.9.2-... but the fetched package has zspec-0.9.1-.... The version prefix is sourced from upstream's own build.zig.zon .version field (still "0.9.1" at the v0.9.2 tag); only the base64 suffix is integrity-relevant. Left the prefix as-is with a comment in build.zig.zon explaining. The real fix is an upstream version bump — filed mentally for next zspec patch.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit fe9f1f2. Configure here.

Comment thread src/tests.zig Outdated
…squash)

main has been red on Linux CI since da97953 (#115 squash-merge) with:

    src/app.zig:11: error: no module named 'nfd' available within module 'root'

The original #106 commit added
`gui_tests_exe.root_module.addImport("nfd", nfd.module("nfd"))` because
once TE callbacks were made `pub fn` (so `std.meta.hasFn` could find
them), the `App.renderFrame` paths the tests exercise pulled in the
nfd-using file-dialog code, which wasn't imported on the test target.

When #115 was rebased / cherry-picked through review-fix cycles, that
single line got dropped from build.zig. Subsequent merges of #115
itself and #119 inherited the broken state and CI started failing on
every push without it being obvious whose change introduced it.

This restores the addImport with an explanatory comment so future
rebases preserve it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces shared zspec-based test fixtures (Factory pattern) to reduce repetitive manual arena.dupe setup in tests, while bumping the zspec dependency to pick up upstream fixes.

Changes:

  • Bump zspec dependency to v0.9.2.
  • Add src/test_fixtures.zig plus a .zon fixture to define reusable ResourceDef and ProjectConfig factories.
  • Update project save/load tests to use the factories and add a new “ProjectConfig overrides round-trip” test.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

File Description
src/tests.zig Switch resource test setup to ResourceFactory and add a new config override round-trip test using ProjectConfigFactory.
src/test_fixtures.zig New shared module defining zspec factories for common test data.
src/test_fixtures/resource.zon New ZON fixture backing the ResourceDef factory defaults.
build.zig.zon Update zspec dependency URL/hash for v0.9.2.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread build.zig.zon
.url = "https://github.com/apotema/zspec/archive/v0.9.1.tar.gz",
.hash = "zspec-0.9.1-jaKLbbX4AwBKANdetxzzWc3UTO0UY0lcJJzTagQHlt5K",
.url = "https://github.com/apotema/zspec/archive/v0.9.2.tar.gz",
.hash = "zspec-0.9.1-jaKLbXgMBACFwbNjflhbMyP113leoYjboxn-1UOP-FGw",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reply: Zig 0.16's package manager rejects this edit — hash mismatch: manifest declares zspec-0.9.2-... but the fetched package has zspec-0.9.1-.... The prefix is baked from upstream's build.zig.zon .version field, which still reads "0.9.1" at the v0.9.2 tag. Only the base64 portion is integrity-checked; the prefix is cosmetic metadata sourced from upstream. Documented in a comment on the field — see df4b631.

Comment thread src/tests.zig
Comment on lines +1934 to +1942
proj.config = test_fixtures.ProjectConfigFactory.build(.{
.name = "factory_overrides",
.title = "Factory Overrides",
.width = 1920,
.height = 1080,
.backend = .sokol,
.initial_scene = "splash",
.engine_version = "1.35.0",
});
Comment thread src/tests.zig Outdated
try expect.equal(cfg.backend, .sokol);
try expect.toBeTrue(std.mem.eql(u8, cfg.initial_scene, "splash"));
try expect.toBeTrue(std.mem.eql(u8, cfg.engine_version, "1.35.0"));
// Unmodified-by-override fields keep their fixture defaults.
- build.zig.zon: leave the `zspec-0.9.1-...` hash prefix as-is and
  explain why in a comment. Both gemini and copilot suggested
  changing it to `zspec-0.9.2-...` to match the URL, but Zig 0.16's
  package manager bakes upstream's own `build.zig.zon` `.version`
  into the hash and rejects manual edits ("hash mismatch: manifest
  declares zspec-0.9.2-... but the fetched package has zspec-0.9.1-...").
  Upstream's `.version` still reads "0.9.1" at the v0.9.2 tag; the
  prefix is cosmetic metadata sourced from there. Only the base64
  portion is integrity-relevant.

- src/tests.zig (cursor + copilot): the `engine_version = "1.35.0"`
  override matched both the factory default and the ProjectConfig
  struct default, making it a no-op. Bumped to "1.36.0" so the
  assertion actually exercises an override path.

- src/tests.zig (copilot): the "non-overridden fields keep their
  fixture defaults" comment claimed coverage of every untouched
  field but only checked `ecs` + `target_fps`. Expanded the
  assertions to also cover `description`, `core_version`,
  `gfx_version`, `assembler_version`, and `resources.len = 0`.

`zig build test` — 180/180 pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@apotema apotema merged commit ac37f70 into main May 15, 2026
4 checks passed
@apotema apotema deleted the feat/zspec-factory-pov branch May 15, 2026 22:15
apotema added a commit that referenced this pull request May 16, 2026
Minor release rolling up the post-0.2.1 PIE viewport editor work:

- #107 / #111 — Game View panel (SHM consumer + ImGui::Image).
- #108 / #115 — macOS IOSurface zero-copy consumer module.
- #112 / #113 — TCP transport restore (JSON control plane).
- #119 — Binary plane decoder (entity/component/flow frames).
- #109 / #122 — ImGui Test Engine coverage of the Game View panel.
- #120 / #123 — Triage of 5 long-silent-passing TE tests.
- #121 — zspec Factory pattern for ProjectConfig + ResourceDef fixtures.
- #124 — Dispatch iosurface consumer on `frame_offer.format`, FBO blit
  for `GL_TEXTURE_RECTANGLE → GL_TEXTURE_2D` so imgui_impl_opengl3 can
  display the zero-copy texture.

Plus several Zig 0.16 compat fixes (preview transport restore, gizmos
empty-index test, TE pub-fn gating, io.Threaded deadlock workarounds)
and ci: gui-tests N>0 assertion (#118).

Paired downstream: labelle-engine v1.37.3 (IOSurface producer) and
labelle-assembler 0.19.0 (raylib PBO publishFrame).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants