Skip to content

test(storage): verify image()/file() reject malformed write shapes end-to-end#795

Merged
borisno2 merged 1 commit into
mainfrom
claude/funny-sagan-eeabn1
Jul 21, 2026
Merged

test(storage): verify image()/file() reject malformed write shapes end-to-end#795
borisno2 merged 1 commit into
mainfrom
claude/funny-sagan-eeabn1

Conversation

@borisno2

Copy link
Copy Markdown
Member

Summary

  • Adds packages/storage/tests/opensaas-image-file-write-validation.test.ts, an integration-style test that exercises the REAL image()/file() field pipeline pieces in the order the Hook Pipeline runs them: field resolveInput → built-in field validation (via the same validateWithZod core's validateFieldRules wraps) → splitColumns.
  • Covers db.columns: 'keystone' (multi-column) mode for both image() and file():
    • The legacy Keystone GraphQL { upload: File } wrapper shape (neither File-like nor already-shaped metadata) now throws a real ValidationError instead of being silently split into null/undefined physical columns — and asserts splitColumns is never reached once validation rejects the value.
    • The three legitimate shapes (null, an already-shaped metadata object with no re-upload, and a File-like value that triggers an upload via a mocked storage provider) all persist correctly with the expected per-part columns.
  • Covers the default single-column (JSON) mode as a comparison baseline for both fields, confirming the same malformed shape already throws today (closing the "we didn't verify single-column mode" gap called out in the downstream report).
  • Adds a patch changeset for @opensaas/stack-storage (test coverage only, no behavior change).

This proves the #789 fix (Hook Pipeline validates a multi-column field's logical value before splitting it) holds end-to-end for the real image()/file() fields, pinning it as a regression guard in both directions.

Test plan

  • pnpm test passes in packages/storage (158/158 tests, including 10 new tests)
  • pnpm lint passes on the new test file
  • pnpm format / prettier check passes
  • pnpm manypkg fix run (no changes needed)
  • Changeset added

Closes #790


Generated by Claude Code

…d-to-end

Adds integration-style tests exercising the real resolveInput -> validate ->
splitColumns pipeline for image()/file() in both db.columns: 'keystone'
(multi-column) and default single-column (JSON) modes, pinning the #789 fix
as a regression guard against silent data corruption.

Closes #790

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q1GQboF8Ym1c4egaAzxkq5
@vercel

vercel Bot commented Jul 21, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
stack-docs Ready Ready Preview, Comment Jul 21, 2026 11:49am

@changeset-bot

changeset-bot Bot commented Jul 21, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 81f1520

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 9 packages
Name Type
@opensaas/stack-storage Patch
@opensaas/stack-storage-s3 Patch
@opensaas/stack-storage-vercel Patch
@opensaas/stack-auth Patch
@opensaas/stack-cli Patch
@opensaas/stack-core Patch
@opensaas/stack-rag Patch
@opensaas/stack-tiptap Patch
@opensaas/stack-ui Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Copy Markdown
Member Author

Code Review

Overview

This PR is purely additive (2 new files, no production code touched): a new integration test file for packages/storage and a patch changeset. It exercises the real image()/file() field pipeline (resolveInput → validation via the same validateWithZod core's validateFieldRules wraps → splitColumns) to prove the #789 fix holds end-to-end, per issue #790's acceptance criteria.

Code quality & conventions

  • Follows the existing multi-column-fields.test.ts conventions closely (same fakeFile/makeContext helper shapes).
  • Stays within package boundaries: rather than reaching into packages/core/src/hooks internals (not importable cross-package), it uses the already-public validateWithZod export from @opensaas/stack-core/internal and a small local runValidateFieldRules wrapper that mirrors core's real validateFieldRules formatting exactly — a good way to test the real validation path without requiring new core exports or touching core at all.
  • Malformed-shape assertions correctly assert a thrown ValidationError (.rejects.toThrow(ValidationError) / expect(() => ...).toThrow(ValidationError)), not just a different return value, per the issue's explicit acceptance criterion.
  • The splitColumns spy (vi.spyOn(field, 'splitColumns') + expect(splitSpy).not.toHaveBeenCalled()) is a nice touch — it directly proves the regression mechanism (silent split-before-validate) can't recur, rather than only inferring it from the throw.
  • Legitimate-shape cases (null, existing metadata, File-like upload) assert actual persisted column values, matching multi-column-read-write.test.ts's style, not just mock call arguments.
  • Single-column (JSON) mode baseline is included and documented as "unaffected by Hook Pipeline: validate multi-column fields before splitting into physical columns #789", closing the gap the downstream report flagged.

Minor notes (non-blocking)

  • context: any in resolveValidateAndSplit and the as any casts on hook-call args are consistent with the pre-existing test file's own patterns (same eslint-disable style), so this isn't a new deviation.
  • ImageMetadata/FileMetadata object literals are duplicated across a few tests (e.g. the "existing" fixtures) rather than factored into shared constants — very minor, and matches the existing file's own repetition style.

Test coverage

Risk

None — no production code changes; this is test-only, matching the patch changeset description.

No changes requested.


Generated by Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for Core Package Coverage (./packages/core)

Status Category Percentage Covered / Total
🟢 Lines 92.63% (🎯 65%) 1145 / 1236
🟢 Statements 91.11% (🎯 65%) 1221 / 1340
🟢 Functions 97.93% (🎯 62%) 190 / 194
🟢 Branches 81.91% (🎯 50%) 820 / 1001
File CoverageNo changed files found.
Generated in workflow #1496 for commit 81f1520 by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for UI Package Coverage (./packages/ui)

Status Category Percentage Covered / Total
🔵 Lines 76.72% 244 / 318
🔵 Statements 76.29% 251 / 329
🔵 Functions 69.15% 74 / 107
🔵 Branches 64.25% 160 / 249
File CoverageNo changed files found.
Generated in workflow #1496 for commit 81f1520 by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for CLI Package Coverage (./packages/cli)

Status Category Percentage Covered / Total
🔵 Lines 79.4% 1496 / 1884
🔵 Statements 79.1% 1556 / 1967
🔵 Functions 86.19% 206 / 239
🔵 Branches 67.31% 655 / 973
File CoverageNo changed files found.
Generated in workflow #1496 for commit 81f1520 by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for Auth Package Coverage (./packages/auth)

Status Category Percentage Covered / Total
🔵 Lines 97.45% 115 / 118
🔵 Statements 97.52% 118 / 121
🔵 Functions 100% 38 / 38
🔵 Branches 92.85% 78 / 84
File CoverageNo changed files found.
Generated in workflow #1496 for commit 81f1520 by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for Storage Package Coverage (./packages/storage)

Status Category Percentage Covered / Total
🔵 Lines 76.65% 197 / 257
🔵 Statements 78.13% 218 / 279
🔵 Functions 85.89% 67 / 78
🔵 Branches 72.98% 181 / 248
File CoverageNo changed files found.
Generated in workflow #1496 for commit 81f1520 by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for RAG Package Coverage (./packages/rag)

Status Category Percentage Covered / Total
🔵 Lines 47.97% 355 / 740
🔵 Statements 48.14% 377 / 783
🔵 Functions 54.26% 70 / 129
🔵 Branches 42.55% 180 / 423
File CoverageNo changed files found.
Generated in workflow #1496 for commit 81f1520 by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for Storage S3 Package Coverage (./packages/storage-s3)

Status Category Percentage Covered / Total
🔵 Lines 100% 40 / 40
🔵 Statements 100% 40 / 40
🔵 Functions 100% 9 / 9
🔵 Branches 100% 19 / 19
File CoverageNo changed files found.
Generated in workflow #1496 for commit 81f1520 by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for Storage Vercel Package Coverage (./packages/storage-vercel)

Status Category Percentage Covered / Total
🔵 Lines 100% 68 / 68
🔵 Statements 100% 71 / 71
🔵 Functions 100% 15 / 15
🔵 Branches 97.87% 46 / 47
File CoverageNo changed files found.
Generated in workflow #1496 for commit 81f1520 by the Vitest Coverage Report Action

@borisno2
borisno2 merged commit 0e603b9 into main Jul 21, 2026
8 of 9 checks passed
@borisno2
borisno2 deleted the claude/funny-sagan-eeabn1 branch July 21, 2026 12:02
@github-actions github-actions Bot mentioned this pull request Jul 21, 2026
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.

storage: image()/file() reject unrecognised write shapes end-to-end in keystone multi-column mode

2 participants