test: cover hosted + local schemas with agent_view test cases#75
test: cover hosted + local schemas with agent_view test cases#75mwbrooks wants to merge 3 commits into
Conversation
Mirrors the canonical agent_view definition from webapp's manifest schema. Sibling of assistant_view; supports agent_description, suggested_prompts (max 4), and actions. Adds local-schema test coverage so edits to the versioned schema files are validated before release. Existing tests run through the GitHub-pinned schema and would not catch local changes.
Reverts the local-schema tests added in the previous commit so this PR matches the existing schema-only feature pattern (mcp_servers, is_mcp_enabled, optional scopes). Coverage will land in a separate PR that refactors the test suite to run every case against both the hosted router schema and the local versioned files.
Refactors v1/v2 test suites so each content-driven case runs against both
the hosted router schema (what consumers fetch) and the local versioned
schema file (what the next release will ship). Router-only behavior like
test_no_metadata stays a single non-parametrized test.
Adds shared agent_view fixture + invalid-mutation table in tests/utils.py
so v1 and v2 stay in sync — agent_view is defined identically across both
versions. New TestManifest{V1,V2}AgentView classes cover valid manifest +
maxItems / maxLength / required field / additionalProperties violations.
agent_view tests are pinned to local-only via SCHEMAS_LOCAL_ONLY until the
property ships in a release; promote to SCHEMAS afterward by deleting the
local-only constant.
WilliamBergamin
left a comment
There was a problem hiding this comment.
I like where this is going 💯 🚀
Left a few comments, the main one is along defining manifest.<feature>.valid.json files to use in the tests rather then using python logic to "compose" new manifests from base json files
Goal: defining manifest.<feature>.valid.json files makes it easier on reviewers and maintainers to understand the changes
| # Each schema-content test runs against both: | ||
| # - the hosted router schema (what IDEs and downstream consumers fetch) | ||
| # - the local versioned schema (what the next release will ship) | ||
| # Router-specific tests like test_no_metadata stay below, outside this matrix. | ||
| SCHEMAS = [ | ||
| pytest.param(get_schema, id="hosted"), | ||
| pytest.param(get_schema_v1, id="local"), | ||
| ] |
There was a problem hiding this comment.
Thats a good idea it prevents regressions 💯
I'm not the biggest fan of the naming maybe we could do
get_schema->load_hosted_schemaget_schema_v1->load_local_schema
|
|
||
| def test_no_metadata(self): | ||
| # GIVEN | ||
| # GIVEN — router falls back to v1 when _metadata is absent |
There was a problem hiding this comment.
Not sure we need this in a comment, maybe we could improve the name of the test instead 🤔
| # THEN validation exception is raised | ||
|
|
||
|
|
||
| class TestManifestV1AgentView: |
There was a problem hiding this comment.
I love having more tests 💯
But I think the tests would be cleaner if we do the following
- Defined the manifest in a specific manifest
jsonfile for the test and load it directly in the test, rather then loading a base manifest and modifying it programmatically, example amanifest.agent_view..valid.jsonfile for the test.- This aims to make the tests and changes more reviewable and maintainable
- Maybe agree on a folder structure or file naming convention that allows to run tests in a "loop" similar to parametrize
- Moved the
TestManifestV1AgentViewto its own class so that this file does not grow out of control
| @@ -10,4 +14,63 @@ def get_json(path: str) -> Dict: | |||
|
|
|||
|
|
|||
| def get_schema() -> Dict: | |||
There was a problem hiding this comment.
| def get_schema() -> Dict: | |
| def get_hosted_schema() -> Dict: |
| MANIFEST_SCHEMA_V1_PATH = "schemas/manifest.schema.1.0.0.json" | ||
| MANIFEST_SCHEMA_V2_PATH = "schemas/manifest.schema.2.0.0.json" |
There was a problem hiding this comment.
Maybe we make this
| MANIFEST_SCHEMA_V1_PATH = "schemas/manifest.schema.1.0.0.json" | |
| MANIFEST_SCHEMA_V2_PATH = "schemas/manifest.schema.2.0.0.json" | |
| class MANIFEST_SCHEMA_FILENAMES(Enum): | |
| V1 = "manifest.schema.1.0.0.json" | |
| V2 = "manifest.schema.2.0.0.json" |
| def get_schema_v1() -> Dict: | ||
| """Local v1 schema — what the next release artifact will ship.""" | ||
| return get_json(MANIFEST_SCHEMA_V1_PATH) | ||
|
|
||
|
|
||
| def get_schema_v2() -> Dict: | ||
| """Local v2 schema — what the next release artifact will ship.""" | ||
| return get_json(MANIFEST_SCHEMA_V2_PATH) |
There was a problem hiding this comment.
Maybe we do something like this with the enum
| def get_schema_v1() -> Dict: | |
| """Local v1 schema — what the next release artifact will ship.""" | |
| return get_json(MANIFEST_SCHEMA_V1_PATH) | |
| def get_schema_v2() -> Dict: | |
| """Local v2 schema — what the next release artifact will ship.""" | |
| return get_json(MANIFEST_SCHEMA_V2_PATH) | |
| def get_local_schema(filename: MANIFEST_SCHEMA_FILENAMES) -> Dict: | |
| path = "schemas" / filename | |
| return get_json(path) |
Summary
Stacks on top of #74 — base branch is
mwbrooks-manifest-agent-view.test_successandtest_invalidcases across both schema surfaces:hosted— the GitHub-pinned router schema that IDEs and downstream consumers actually fetchlocal— the versioned schema files inschemas/that the next release will shipagent_viewvalid fixture and a shared invalid-mutation table intotests/utils.py. v1 and v2 reuse the same data becauseagent_viewis defined identically across versions.TestManifest{V1,V2}AgentViewcovering valid manifest + 4 invalid mutations (maxItems onsuggested_prompts, missingdescriptiononactions[],agent_descriptionover 300 chars,additionalPropertiesrejected).SCHEMAS_LOCAL_ONLYuntil the property is published in a release. Once published, promote them by deleting the local-only constant.Why
Existing tests validate against the GitHub-pinned router (currently
v0.4.0), so edits to the local versioned schema files were never exercised before release. This made past PRs likemcp_serversandis_mcp_enabledship without local test coverage. The hosted+local matrix means new properties get validated locally on every PR while still confirming the released router stays compatible with the canonical fixtures.Test plan
pytest -v— 20/20 pass (10 base × 2 schemas + 10 agent_view local-only)./scripts/lint.sh— cleanFollow-ups
agent_viewships in a release, deleteSCHEMAS_LOCAL_ONLYso the agent_view tests run against the hosted schema too.