A stateful mock GitHub API engine for deterministic tests and local automation.
Simulacat Core extends The Frontside's Simulacrum GitHub API example into a
reusable library for higher-level test harnesses. It is the engine behind
Simulacat, a Python pytest fixture for
stateful GitHub API mocking, and the planned Rust companion Rentaneko.
GitHub-heavy tests usually rot in one of two ways: they either hit the real API and become brittle, or they rely on static fixtures that cannot express stateful behaviour.
- Model GitHub as a testable system: Seed users, organizations, repositories, branches, blobs, and installations, then query them through REST and GraphQL.
- Stay deterministic: Run the same simulation locally and in CI without rewriting production code around "test mode" flags.
- Extend where you need to: Add store slices, OpenAPI handlers, and Express routes for product-specific behaviour.
- Share one engine across languages: Use the same simulator core from Python fixtures today and Rust fixtures tomorrow.
bun add simulacat-coreimport {simulation, type InitialState} from 'simulacat-core';
const initialState: InitialState = {
users: [{login: 'test', organizations: ['frontside']}],
organizations: [{login: 'frontside'}],
repositories: [{owner: 'frontside', name: 'test-repo'}],
branches: [{owner: 'frontside', repo: 'test-repo', name: 'main'}],
blobs: [{owner: 'frontside', repo: 'test-repo', path: 'README.md'}]
};
const app = simulation({initialState});
app.listen(3300, () => {
console.log('Simulacat Core is listening on http://localhost:3300');
});Point your GitHub client at http://localhost:3300, then visit
http://localhost:3300/simulation to inspect the available routes.
simulation() accepts a single GitHubSimulatorArgs object.
initialState: Seeds users, organizations, repositories, branches, and blobs. Organizations also generate installation fixtures automatically.apiUrl: Changes the mounted REST API root. The default is/.apiSchema: Uses a bundled schema such asapi.github.com.jsonor a custom schema path on disk.extend.extendStore: Adds store schema, actions, or selectors alongside the built-in GitHub slices.extend.openapiHandlers: Registers extra OpenAPI operation handlers that can read from the shared simulation store.extend.extendRouter: Adds plain Express routes next to the built-in health, OAuth, and GraphQL routes.
You can layer custom routes and handlers on top of the core GitHub behaviour without forking the package:
import {simulation, type InitialState} from 'simulacat-core';
const initialState: InitialState = {
users: [{login: 'test', organizations: []}],
organizations: [{login: 'frontside'}],
repositories: [{owner: 'frontside', name: 'test-repo'}],
branches: [{owner: 'frontside', repo: 'test-repo', name: 'main'}],
blobs: []
};
const app = simulation({
initialState,
extend: {
extendRouter: (router) => {
router.get('/hello-world', (_request, response) => {
response.json({message: 'hello from simulacat-core'});
});
},
openapiHandlers: (simulationStore) => ({
'repos/list-tags': async () => ({
status: 200,
json: [
{
name: `v${simulationStore.schema.repositories.selectTableAsList(
simulationStore.store.getState()
).length}.0.0`
}
]
})
})
}
});| Surface | Coverage today | Notes |
|---|---|---|
| REST routes | Installations, repository lists, branches, blobs, trees, commit status, authenticated user, and org memberships | See docs/api-reference.md for the exact route list. Authenticated-user routes require an actor header; see the users guide for details. |
| GraphQL root queries | viewer, organization, organizations, repository, and repositoryOwner |
Connection pagination uses Relay-style cursors. |
| GraphQL nested fields | Repository owners, repository topics, languages, and user organizations | Some connections are intentionally stubbed with empty results for now. |
| Platform routes | /health, /graphql, OAuth authorize, and OAuth access token endpoints |
Useful for local harness bootstrapping and login flows. |
The package exports both the simulation factory and the schema helpers used to seed fixtures.
InitialState: Alias for the input shape accepted bysimulation().githubUserSchema: Seeds GitHub users and fills in default names, emails, avatars, and timestamps.githubOrganizationSchema: Seeds organizations and derives GitHub-style URLs plus default metadata.githubRepositorySchema: Seeds repositories and expands them with canonical REST-style URLs and default visibility metadata.githubBranchSchema: Seeds branch data, defaulting tomain.githubBlobSchema: Seeds repository contents. A blob must specify eitherpathorsha; either lookup style is supported.buildRepositoryFixtureandbuildBranchFixture: Parse individual fixtures through the public schemas and return the expanded entities.
Repository identity is scoped by owner. Use owner/name for repositories and
owner/repo:name for branches; two owners can each seed a repository with the
same short name without colliding. Derived repository node_id values encode
Repository:owner/name.
- Store-backed REST handlers for core GitHub simulator workflows.
- GraphQL support for repository, owner, and pagination-driven test queries.
- Typed
InitialStateinput for seeding stateful test fixtures quickly. - Extension hooks for custom store state, OpenAPI handlers, and router behaviour.
- Bundled GitHub REST and GraphQL schemas for local simulation.
- API reference — simulation arguments, exported schemas, and supported API operations.
- User guide — canonical key formats, fixture builders, store key helpers, and breaking changes introduced in 1.1.1 and 1.2.1.
- Architecture guide — how seeded state flows through the store, REST, and GraphQL layers.
- Development guide — local workflows, quality gates, and schema regeneration.
- GitHub REST API audit — current REST coverage, scriptability, and gaps.
- GitHub GraphQL API audit — current GraphQL behaviour and limitations.
- Roadmap — planned delivery slices and priorities.
- Schema notes — bundled REST and GraphQL schema details.
Simulacat Core is derived from the GitHub API example shipped with Simulacrum by The Frontside. This repository keeps that "scriptable fake over inert fixtures" spirit, then pushes it towards stateful testing for the df12 toolchain.
MIT — see LICENSE for details.
Contributions are welcome. Please read AGENTS.md before making changes, so your work matches the repository's build, testing, and commit rules.