Skip to content

fix: studio CI test failures - fix simulateBrowser mock handlers#1155

Merged
hotlong merged 1 commit intomainfrom
copilot/fix-ci-errors-7957bead-2272-48a0-a2b8-adff3e5c8ee6
Apr 15, 2026
Merged

fix: studio CI test failures - fix simulateBrowser mock handlers#1155
hotlong merged 1 commit intomainfrom
copilot/fix-ci-errors-7957bead-2272-48a0-a2b8-adff3e5c8ee6

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 15, 2026

Summary

Fixes all 9 failing tests in @objectstack/studio#test (CI run #24456193896) by correcting the simulateBrowser MSW mock handlers in apps/studio/src/mocks/simulateBrowser.ts.

Root Causes & Fixes

1. Data endpoint ignored query parameters (4 test failures)

Tests: api.test.ts (3 tests), api-discovery.test.ts (1 test)

The GET /data/:object handler called ql.find(params.object) without passing any query options. The client sends top, skip, sort, select, and filter parameters, but all were ignored — returning all records instead of the filtered/paginated subset.

Fix: Added parseQueryOptions() helper that parses URL search params into ObjectQL EngineQueryOptions (limit, offset, orderBy, fields, where), and passes them to ql.find().

2. Metadata types endpoint missing runtime types (2 test failures)

Tests: verify-metadata.test.ts — "should include agent/tool in metadata types"

The GET /meta handler used ql.registry.getRegisteredTypes() which only returns SchemaRegistry types (package, data, app, object), missing runtime types (agent, tool, etc.) registered by AIServicePlugin via MetadataService.

Fix: Now uses protocol.getMetaTypes() which merges both SchemaRegistry and MetadataService types.

3. Metadata items endpoint only queried SchemaRegistry (2 test failures)

Tests: verify-metadata.test.ts — "should list registered agents/tools"

The GET /meta/:type handler used ql.registry.listItems(type) which only returns SchemaRegistry items. Agents and tools are registered in MetadataService, not SchemaRegistry.

Fix: Now uses protocol.getMetaItems({ type }) which queries both registries.

4. Object list endpoint returned wrong format (1 test failure)

Test: verify-metadata.test.ts — "should fetch list of objects"

The GET /meta/object handler returned ql.getObjects() (which doesn't exist, defaulting to {}) instead of the spec-compliant { type: 'object', items: [...] } format.

Fix: Now uses protocol.getMetaItems({ type: 'object' }) which returns the correct format.

Verification

  • ✅ All 56 studio tests pass (8/8 test files)
  • ✅ Full monorepo test suite passes (85/85 tasks)

…query params and metadata protocol

The simulateBrowser mock handlers had three categories of issues:

1. GET /data/:object ignored query parameters (top, skip, sort, select, filter).
   Added parseQueryOptions() to parse URL search params and pass them to ql.find().

2. Metadata type/list endpoints used SchemaRegistry directly, missing runtime types
   (agent, tool) registered via MetadataService. Now uses protocol service which
   merges both SchemaRegistry and MetadataService data.

3. Metadata object list endpoint returned a plain object instead of the expected
   { type: 'object', items: [...] } format. Now uses protocol.getMetaItems().

Agent-Logs-Url: https://github.com/objectstack-ai/framework/sessions/91f259ad-90cc-408e-a96c-056b04824a93

Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 15, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
objectstack-demo Ready Ready Preview, Comment Apr 15, 2026 1:51pm
spec Ready Ready Preview, Comment Apr 15, 2026 1:51pm

Request Review

Copilot AI requested a review from hotlong April 15, 2026 13:51
@github-actions github-actions bot added size/s documentation Improvements or additions to documentation labels Apr 15, 2026
@hotlong hotlong marked this pull request as ready for review April 15, 2026 14:12
Copilot AI review requested due to automatic review settings April 15, 2026 14:12
@hotlong hotlong merged commit dfe08e6 into main Apr 15, 2026
14 checks passed
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes Studio CI failures by making the simulateBrowser MSW mock behave closer to the real ObjectStack HTTP API, especially for queryable data endpoints and protocol-compliant metadata endpoints.

Changes:

  • Added query-string parsing for GET /api/v1/data/:object and passed the parsed options into ql.find(...).
  • Switched metadata mocks (/api/v1/meta*) to use the protocol service (getMetaTypes/getMetaItems/getMetaItem) so runtime-registered metadata types/items are included.
  • Documented the fix in the Studio changelog.

Reviewed changes

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

File Description
apps/studio/src/mocks/simulateBrowser.ts Adds parseQueryOptions() and updates MSW handlers to use query options for data find and protocol-backed metadata endpoints.
apps/studio/CHANGELOG.md Adds a patch note describing the simulateBrowser mock handler fixes.

Comment on lines +30 to +31
try { query.orderBy = JSON.parse(val); } catch {
query.orderBy = val.split(',').map((s: string) => s.trim());
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

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

parseQueryOptions() maps the sort query param to query.orderBy as a string array when the value is comma-separated (e.g. "-created_at"). EngineQueryOptions.orderBy is an array of SortNode objects ({ field, order }), and the in-memory driver’s applySort() ignores string items, so sorting won’t be applied for the common sort=-field form sent by ObjectStackClient.data.find(). Convert string tokens into SortNode objects (handle leading '-' for desc) instead of returning raw strings.

Suggested change
try { query.orderBy = JSON.parse(val); } catch {
query.orderBy = val.split(',').map((s: string) => s.trim());
try {
query.orderBy = JSON.parse(val);
} catch {
query.orderBy = val
.split(',')
.map((s: string) => s.trim())
.filter(Boolean)
.map((token: string) => ({
field: token.startsWith('-') ? token.slice(1) : token,
order: token.startsWith('-') ? 'desc' : 'asc',
}));

Copilot uses AI. Check for mistakes.
Comment on lines +39 to +42
case 'filter':
case '$filter':
try { Object.assign(where, JSON.parse(val)); } catch { /* ignore malformed */ }
break;
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

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

filter is JSON-parsed and merged into where via Object.assign(where, JSON.parse(val)). When the client sends an AST/array filter (it serializes arrays into the filter param), this produces a { "0": ..., "1": ... } object rather than a valid where condition, so filtering will silently fail. If the parsed value is an array (or already a FilterCondition shape), assign it to query.where directly rather than merging into an object.

Copilot uses AI. Check for mistakes.
Comment on lines +43 to +46
default:
// Individual key-value filter params (e.g. id=abc)
where[key] = val;
break;
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

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

ObjectStackClient.data.find() can send aggregations (JSON) and groupBy (comma-separated) query params, but parseQueryOptions() currently treats unknown params as field filters and puts them into where. This breaks aggregation queries by turning control params into WHERE conditions. Add explicit parsing/forwarding for these keys (or explicitly ignore them) so they don’t end up in where.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants