Skip to content

Add regression coverage for Database Explorer read-only query contract - #187

Open
karan-cspl wants to merge 1 commit into
github-samples:mainfrom
karan-cspl:karan-cspl-database-explorer-read-only-regression-t
Open

karan-cspl wants to merge 1 commit into
github-samples:mainfrom
karan-cspl:karan-cspl-database-explorer-read-only-regression-t

Conversation

@karan-cspl

Copy link
Copy Markdown

Description

Adds isolated Vitest regression coverage for the Database Explorer extension's read-only SQL query contract across both its HTTP (/api/query, /api/tables) and canvas-action (run_query, list_tables) entry points. Previously, vitest.config.ts only discovered tests under db/ and src/, and .github/extensions/database-explorer/extension.mjs executed top-level await joinSession(...) with host-only imports (@libsql/client, @github/copilot-sdk/extension), preventing direct unit and integration testing of the shared query validation and execution paths.

Related Issue

Fixes: #164
Closes #164

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to change)
  • 📚 Documentation update
  • 🧪 Test update
  • 🔧 Refactor (no functional changes)

Changes Made

  • Extracted shared query normalization (stripCommentsAndValidateSingleStatement), validation (validateReadOnlyQuery), value formatting (normalizeValue), query execution (executeQuery, listTables), HTTP server (startServer), and canvas definition factory (createDatabaseExplorerCanvas) into .github/extensions/database-explorer/query-policy.mjs (with .d.mts TypeScript declarations) using injectable client and SDK dependencies.
  • Updated .github/extensions/database-explorer/extension.mjs to delegate to ./query-policy.mjs while preserving runtime behavior.
  • Added .github/extensions/database-explorer/query-policy.test.ts covering all five required scenarios against a disposable node:sqlite fixture database:
    • accepts supported read-only single-statement queries
    • rejects invalid input and requests outside the read-only contract (29 table-driven cases)
    • does not invoke the query executor after validation rejects a request
    • preserves fixture rows and schema while serving the read-only interface
    • applies the same policy through HTTP and canvas actions
  • Updated vitest.config.ts and tsconfig.tsgo.json to include .github/extensions/**/*.test.ts and .github/extensions/**/*.ts.

Testing

  • npm run test:unit -- --reporter=verbose - Passed (5 test files, 72 tests passed, including all 33 tests in .github/extensions/database-explorer/query-policy.test.ts)
  • npm run lint - Passed (0 errors)
  • npm run typecheck:all (npm run typecheck + npm run typecheck:astro) - Passed (0 errors, 0 warnings, 0 hints across 37 files)

Data Layer Changes

  • Ran npm run test:unit - all tests pass
  • Added/updated Vitest tests for data-layer changes
  • Generated a migration (npm run db:generate) for any schema change (N/A - no schema changes)

Frontend Changes

  • Ran npm run test:e2e - all tests pass (N/A - no frontend UI changes)
  • Added data-testid attributes to interactive elements (N/A - no frontend UI changes)
  • Verified build succeeds (npm run build) (N/A - no frontend UI changes)

Checklist

  • My code follows the project's coding standards
  • I have used explicit TypeScript types for function parameters and return values
  • I have built the UI with Astro components and Tailwind CSS utility classes (dark theme)
  • I have updated documentation (README, instruction files) if needed
  • My changes are focused on a single concern
  • I have written clear commit messages explaining what and why

Additional Notes

Discovered test names in .github/extensions/database-explorer/query-policy.test.ts:

  • Database Explorer read-only query contract > accepts supported read-only single-statement queries
  • Database Explorer read-only query contract > rejects invalid input and requests outside the read-only contract > rejects <case> with "<expectedError>" (29 table-driven policy cases)
  • Database Explorer read-only query contract > does not invoke the query executor after validation rejects a request
  • Database Explorer read-only query contract > preserves fixture rows and schema while serving the read-only interface
  • Database Explorer read-only query contract > applies the same policy through HTTP and canvas actions

Extract shared query validation, execution, HTTP server, and canvas definition factory into query-policy.mjs with injectable dependencies, add Vitest regression coverage across disposable SQLite fixtures and both entry points, and include extension tests in Vitest and tsgo discovery.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 3, 2026 06:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The rejection matrix omits SQLite-supported WITH-prefixed mutations that the shared validator accepts, allowing both entry points to modify data despite passing the no-execution and unchanged-state tests.

1 open issue
What changed in this PR

Adds isolated regression coverage for the Database Explorer’s read-only query contract, addressing issue #164 without requiring a hosted SDK session.

Changes:

  • Extracts query handling, HTTP serving, and canvas actions into an importable module with injectable dependencies.
  • Adds disposable SQLite tests for accepted queries, rejected inputs, unchanged database state, and HTTP/canvas consistency.
  • Includes extension tests in Vitest discovery and TypeScript checks.
File Description
vitest.config.ts Enables discovery of extension-local tests.
tsconfig.tsgo.json Includes extension TypeScript files in type checks.
.github/​extensions/​database-explorer/​query-policy.test.ts Adds query-contract and entry-point regression coverage.
.github/​extensions/​database-explorer/​query-policy.mjs Extracts shared policy and runtime handlers for isolated testing.
.github/​extensions/​database-explorer/​query-policy.d.mts Declares types for the extracted module and injectable dependencies.
.github/​extensions/​database-explorer/​extension.mjs Delegates to the extracted module while retaining SDK registration.

Review effort: Balanced

Comment on lines +163 to +165
{ label: 'INSERT statement', input: "INSERT INTO publishers (name) VALUES ('Rogue')", expectedError: 'Only read-only SELECT and WITH queries are allowed.' },
{ label: 'UPDATE statement', input: "UPDATE games SET funding_goal = 0 WHERE id = 1", expectedError: 'Only read-only SELECT and WITH queries are allowed.' },
{ label: 'DELETE statement', input: 'DELETE FROM games WHERE id = 1', expectedError: 'Only read-only SELECT and WITH queries are allowed.' },
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.

[P1] Add regression coverage for Database Explorer's read-only query contract

3 participants