fix: use .[][].name in jq for wrapped JSON response

API returns { "resources": [...] } not bare arrays, so .[].name
produced no output. Use .[][].name to unwrap the outer object first.
Also auto-load .env in pr.sh.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Michal
2026-02-23 19:26:47 +00:00
parent 8d296b6b7c
commit 0a641491a4
4 changed files with 28 additions and 16 deletions

View File

@@ -72,16 +72,19 @@ describe('fish completions', () => {
}
});
it('resource name functions use jq (not regex) to avoid matching nested name fields', () => {
// Regex like "name":\s*"..." on JSON matches nested server names inside project objects.
// Must use jq -r '.[].name' to extract only top-level names.
it('resource name functions use jq .[][].name to unwrap wrapped JSON and avoid nested matches', () => {
// API returns { "resources": [...] } not [...], so .[].name fails silently.
// Must use .[][].name to unwrap the outer object then iterate the array.
// Also must not use string match regex which matches nested name fields.
const resourceNamesFn = fishFile.match(/function __mcpctl_resource_names[\s\S]*?^end/m)?.[0] ?? '';
const projectNamesFn = fishFile.match(/function __mcpctl_project_names[\s\S]*?^end/m)?.[0] ?? '';
expect(resourceNamesFn, '__mcpctl_resource_names must use jq').toContain("jq -r '.[].name'");
expect(resourceNamesFn, '__mcpctl_resource_names must use jq .[][].name').toContain("jq -r '.[][].name'");
expect(resourceNamesFn, '__mcpctl_resource_names must not use string match on name').not.toMatch(/string match.*"name"/);
// Guard against .[].name (single bracket) which fails on wrapped JSON
expect(resourceNamesFn, '__mcpctl_resource_names must not use .[].name (needs .[][].name)').not.toMatch(/jq.*'\.\[\]\.name'/);
expect(projectNamesFn, '__mcpctl_project_names must use jq').toContain("jq -r '.[].name'");
expect(projectNamesFn, '__mcpctl_project_names must use jq .[][].name').toContain("jq -r '.[][].name'");
expect(projectNamesFn, '__mcpctl_project_names must not use string match on name').not.toMatch(/string match.*"name"/);
});
@@ -126,9 +129,11 @@ describe('bash completions', () => {
expect(bashFile).toContain('--project');
});
it('resource name function uses jq (not grep regex) to avoid matching nested name fields', () => {
it('resource name function uses jq .[][].name to unwrap wrapped JSON and avoid nested matches', () => {
const fnMatch = bashFile.match(/_mcpctl_resource_names\(\)[\s\S]*?\n\s*\}/)?.[0] ?? '';
expect(fnMatch, '_mcpctl_resource_names must use jq').toContain("jq -r '.[].name'");
expect(fnMatch, '_mcpctl_resource_names must use jq .[][].name').toContain("jq -r '.[][].name'");
expect(fnMatch, '_mcpctl_resource_names must not use grep on name').not.toMatch(/grep.*"name"/);
// Guard against .[].name (single bracket) which fails on wrapped JSON
expect(fnMatch, '_mcpctl_resource_names must not use .[].name (needs .[][].name)').not.toMatch(/jq.*'\.\[\]\.name'/);
});
});