Skip to content

eng-260#358

Merged
Connorbelez merged 7 commits intomainfrom
Connorbelez/eng-260-implement
Mar 31, 2026
Merged

eng-260#358
Connorbelez merged 7 commits intomainfrom
Connorbelez/eng-260-implement

Conversation

@Connorbelez
Copy link
Copy Markdown
Owner

@Connorbelez Connorbelez commented Mar 31, 2026

eng-260

eng-260

Summary by Sourcery

Add comprehensive CRM EAV test harness and high-level specification docs, plus new integration tests for the view engine and native system adapters.

Documentation:

  • Add ENG-260 spec and chunk task/context documentation describing CRM test harness, record/view/system adapter behaviors, and planned link tests.

Tests:

  • Introduce shared CRM convex-test harness with identities and seed helpers for objects, fields, and records.
  • Add metadata compiler tests covering capability derivation and lifecycle on field create/update/deactivate.
  • Add record CRUD tests validating value routing, validation, soft delete behavior, and audit logging.
  • Add view engine tests for table, kanban, and calendar views, including filters, pagination, schema, integrity, and Kanban moves.
  • Add system adapter tests for native table querying, column resolution, and UnifiedRecord parity between EAV and native records.
  • Add an end-to-end CRM walkthrough test covering object/field setup, views, records, grouping, and search, plus scaffolding for future link tests.

Summary by CodeRabbit

  • Tests

    • Added comprehensive test suites for CRM record management, including create, update, delete, and query operations across multiple field types.
    • Added view engine tests validating table, kanban, and calendar view functionality with filtering and sorting.
    • Added system adapter tests for native table integration and unified record handling.
    • Added end-to-end integration test covering the complete CRM workflow.
  • Documentation

    • Added implementation guides and test context documentation for CRM features across four sequential specification chunks.

@linear
Copy link
Copy Markdown

linear bot commented Mar 31, 2026

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 31, 2026

📝 Walkthrough

Walkthrough

This PR introduces comprehensive test infrastructure and integration test suites for an EAV-based CRM system. It adds a shared test harness factory with identity fixtures and seeding helpers, plus five test suites covering metadata compilation, record CRUD, system adapters, view engine querying, end-to-end workflows, and scaffolded link tests, alongside four sequential specification chunks documenting test requirements.

Changes

Cohort / File(s) Summary
Test Helpers & Infrastructure
convex/crm/__tests__/helpers.ts
Introduces shared CRM test harness factory with identity fixtures (admin, user, different org), identity-scoped handle wrappers, and seeding utilities for objects, fields, and records.
Metadata & Capability Tests
convex/crm/__tests__/metadataCompiler.test.ts
Pure and integration tests for field-type-to-capability derivation across 14 field types, including capability creation, update re-derivation, deactivation removal, and indexed querying.
Record CRUD Tests
convex/crm/__tests__/records.test.ts
Comprehensive tests for record create/update/delete operations, verifying typed value-table routing, label value derivation, validation (required fields, type matching, unknown fields), org scoping, update semantics, soft-deletion behavior, and audit logging.
View Engine Tests
convex/crm/__tests__/viewEngine.test.ts
End-to-end view querying tests covering table/kanban/calendar behaviors, filter operators (eq, contains, numeric ranges, boolean), pagination, kanban grouping, calendar date-range filtering, view integrity (needsRepair on field deactivation), and kanban record moving with audit events.
System Adapters Tests
convex/crm/__tests__/systemAdapters.test.ts
Integration tests for native table system adapters, including column-path resolution with nested paths and date coercion, queryable native records via indexes, bootstrapped system objects (mortgage, borrower, etc.), and unified record contract validation across EAV and native records.
Walkthrough & Links Tests
convex/crm/__tests__/walkthrough.test.ts, convex/crm/__tests__/links.test.ts
End-to-end integration test covering object/field/view creation, capability verification, record CRUD, kanban operations, search, and performance assertion; scaffolded link-type tests marked as skipped (pending implementation).
Specification Documentation
specs/ENG-260/tasks.md, specs/ENG-260/chunks/manifest.md, specs/ENG-260/chunks/chunk-0[1-4]-*/...
Master task list and four sequential specification chunks documenting test requirements: (1) test harness and metadata compiler, (2) record CRUD validation, (3) view engine behaviors and filters, (4) system adapters, links, and end-to-end walkthrough, including context, API references, and expected test outcomes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • eng-249 and eng-250 #350: The main PR's seeding helpers and record CRUD tests directly depend on and validate the record/value table schemas and mutations introduced in this retrieved PR.
  • eng-251 #351: The main PR's record query and walkthrough tests exercise the queryRecords, getRecord, and searchRecords handlers and search index implemented in this PR.
  • eng-253 #355: The main PR's view engine tests and helpers depend on view-related query APIs (queryViewRecords, getViewSchema, moveKanbanRecord) exported in this PR.

Poem

🐰 A harness built with care so fine,
Test helpers weave through EAV's design,
Records hop, views bloom bright,
Metadata compiler gets it right,
The CRM garden's in full flight! 🌻

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The pull request title 'eng-260' is vague and non-descriptive, providing only a ticket number without conveying any meaningful information about the changeset. Use a descriptive title that summarizes the main change, such as 'Add CRM test harness, metadata compiler, and integration tests for view engine and adapters' or 'Implement ENG-260 CRM EAV test suite with helpers, metadata, records, views, and adapters'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch Connorbelez/eng-260-implement

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Owner Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Mar 31, 2026

Reviewer's Guide

Adds a comprehensive CRM EAV test harness and multiple high‑level test suites covering view engine behavior, system adapters over native tables, and shared CRM testing utilities/specs, to validate end‑to‑end behavior of the CRM layer and its integration with native data sources.

File-Level Changes

Change Details Files
Introduce a shared CRM test harness and seeding utilities for convex-test, including identity fixtures and helpers to create objects, fields, and records via real CRM mutations.
  • Create a reusable convex-test harness wired to the main schema and module globbing.
  • Register the convex-audit-log test component so CRM mutations that log audit events work during tests.
  • Define standard admin/user/different-org test identities that satisfy CRM auth middleware expectations.
  • Provide seedObjectWithFields to create an objectDef plus fieldDefs and return IDs and the auto-created default view.
  • Provide seedRecord to create CRM records via public mutations rather than direct DB access.
convex/crm/__tests__/helpers.ts
Add integration tests for the CRM view engine covering table, kanban, and calendar views, view filters, schema, integrity, and kanban record moves.
  • Seed a canonical Lead object with text, select, date, currency, and boolean fields reused across tests.
  • Validate table views return columns in displayOrder, only visible fields in row data, and support cursor-based pagination.
  • Validate kanban views group records by select value, include a "No Value" group for missing values, and keep group counts consistent with record arrays.
  • Validate calendar views return events constrained to a date range and exclude records outside the range.
  • Test viewFilters by inserting filter rows directly and checking eq/contains/is_true behavior on select, text, and boolean fields.
  • Exercise getViewSchema to ensure columns include hasSortCapability flags according to field type.
  • Ensure deactivating a bound field marks views as needsRepair and that querying such views throws.
  • Verify moveKanbanRecord updates the underlying field value and that dropping into the No Value group clears the bound field.
convex/crm/__tests__/viewEngine.test.ts
Add tests for CRM system adapters, native table querying, column path resolution, and the UnifiedRecord contract between EAV and native records.
  • Unit-test resolveColumnPath as a pure function for simple and nested paths, date/datetime coercion, missing paths, and pass-through of non-date values.
  • Use convex-test to seed native users/brokers/properties/mortgages rows, then bootstrap CRM system objects for a test org.
  • Verify queryRecords over a bootstrapped system object (mortgage) returns native-backed UnifiedRecords with correctly mapped and coerced fields.
  • Assert org scoping on native queries by seeding mortgages for two orgs and confirming only caller-org data is returned after bootstrap.
  • Validate that EAV-backed and native-backed records share identical top-level UnifiedRecord keys and expected _kind values.
convex/crm/__tests__/systemAdapters.test.ts
Add ENG-260 specification/task documents describing chunked work, contexts, and planned (including some not-yet-implemented) tests for CRM EAV, views, adapters, links, and walkthrough.
  • Document chunked task breakdown for ENG-260 and mark completed tasks, including helpers, metadata compiler, record CRUD, view engine, adapters, links scaffolding, and walkthrough.
  • Provide contextual docs for helpers/metadata, record CRUD, view engine, and system adapters/links/walkthrough, outlining architecture, APIs, and test strategies.
  • Spell out detailed test plans for metadata compiler, record CRUD, view engine, system adapters, links (largely as future skipped tests), and an end-to-end walkthrough.
  • Record expected test command usage and quality gates (bun test/check/typecheck) for the ENG-260 effort.
specs/ENG-260/tasks.md
specs/ENG-260/chunks/manifest.md
specs/ENG-260/chunks/chunk-01-helpers-metadata/context.md
specs/ENG-260/chunks/chunk-01-helpers-metadata/tasks.md
specs/ENG-260/chunks/chunk-02-record-crud/context.md
specs/ENG-260/chunks/chunk-02-record-crud/tasks.md
specs/ENG-260/chunks/chunk-03-view-engine/context.md
specs/ENG-260/chunks/chunk-03-view-engine/tasks.md
specs/ENG-260/chunks/chunk-04-adapters-links-walkthrough/context.md
specs/ENG-260/chunks/chunk-04-adapters-links-walkthrough/tasks.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@Connorbelez Connorbelez marked this pull request as ready for review March 31, 2026 03:42
Copilot AI review requested due to automatic review settings March 31, 2026 03:42
Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Sorry @Connorbelez, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

Copy link
Copy Markdown

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

Copy link
Copy Markdown

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

This PR introduces a Convex/Vitest integration test harness for the CRM EAV layer and adds a suite of high-level integration tests (metadata compiler, record CRUD, view engine, native system adapters), along with ENG-260 spec/task documentation to describe the intended coverage and architecture touchpoints.

Changes:

  • Added shared CRM convex-test harness utilities (identities + seeding helpers) to support consistent integration testing.
  • Added new CRM integration test suites for capabilities derivation, record CRUD behavior, view querying/moves, and native-record adapter behavior (plus a skipped links scaffold).
  • Added ENG-260 spec docs (chunk contexts + task lists + manifest) to document the test plan and architecture expectations.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
specs/ENG-260/tasks.md Master task list describing intended test coverage and validation steps.
specs/ENG-260/chunks/manifest.md Chunk breakdown and execution order for ENG-260 work.
specs/ENG-260/chunks/chunk-01-helpers-metadata/tasks.md Task spec for harness + metadata compiler tests.
specs/ENG-260/chunks/chunk-01-helpers-metadata/context.md Context for harness setup, fluent middleware expectations, and audit-log registration.
specs/ENG-260/chunks/chunk-02-record-crud/tasks.md Task spec for record CRUD testing scenarios.
specs/ENG-260/chunks/chunk-02-record-crud/context.md Context on value routing, validation rules, labelValue, and audit actions.
specs/ENG-260/chunks/chunk-03-view-engine/tasks.md Task spec for view engine test scenarios.
specs/ENG-260/chunks/chunk-03-view-engine/context.md Context on view APIs, filters schema/operators, integrity/repair behavior, and kanban moves.
specs/ENG-260/chunks/chunk-04-adapters-links-walkthrough/tasks.md Task spec for system adapter tests, links scaffolding, and walkthrough test.
specs/ENG-260/chunks/chunk-04-adapters-links-walkthrough/context.md Context for system adapter architecture + bootstrap + walkthrough flow.
convex/crm/tests/helpers.ts New shared convex-test harness (audit-log registration) + identities + seed helpers.
convex/crm/tests/metadataCompiler.test.ts Tests for deriveCapabilities and capability lifecycle via mutations.
convex/crm/tests/records.test.ts Record CRUD integration tests across types, validation, soft delete, and org scoping.
convex/crm/tests/viewEngine.test.ts View engine integration tests for table/kanban/calendar + filters + integrity + kanban moves.
convex/crm/tests/systemAdapters.test.ts System adapter tests for resolveColumnPath plus native querying via system bootstrap.
convex/crm/tests/walkthrough.test.ts End-to-end walkthrough test across object/fields/views/records/search/perf check.
convex/crm/tests/links.test.ts Skipped scaffold for future ENG-257 link backend tests.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread convex/crm/__tests__/helpers.ts
Comment thread convex/crm/__tests__/records.test.ts
Comment thread convex/crm/__tests__/viewEngine.test.ts
Comment thread convex/crm/__tests__/viewEngine.test.ts
Comment thread convex/crm/__tests__/systemAdapters.test.ts
Comment thread convex/crm/__tests__/walkthrough.test.ts Outdated
Comment thread convex/crm/__tests__/walkthrough.test.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
convex/crm/__tests__/walkthrough.test.ts (1)

169-192: Re-query the kanban view after the status change.

Step 8 currently proves the row payload changed, but not that the board regrouped. If the kanban aggregation/cache stops reflecting record updates, this walkthrough still passes. Re-run queryViewRecords for kanbanViewId and assert the counts moved from New to Contacted.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@convex/crm/__tests__/walkthrough.test.ts` around lines 169 - 192, After
updating the record via asAdmin(t).mutation(api.crm.records.updateRecord),
re-query the kanban view by calling
asAdmin(t).query(api.crm.viewQueries.queryViewRecords, { viewDefId:
kanbanViewId, limit: 100 }) and assert the kanban buckets reflect the move
(e.g., find the bucket for status "New" and "contacted" in the returned rows or
grouping metadata and verify the count for "New" decreased and "contacted"
increased compared to the pre-update values); use the same approach you used for
tableViewId (tableResult/updatedTable) but target kanbanViewId and compare
counts to ensure the board regrouped after the status change.
convex/crm/__tests__/systemAdapters.test.ts (2)

334-447: Assert the _kind discriminator as part of the contract.

This parity check only compares keys. If EAV records were accidentally emitted with _kind: "native" (or vice versa), the test would still pass because _kind is present on both objects. Please assert the expected discriminator values alongside the key-set comparison.

💡 Minimal hardening
 		const eavRecord = eavResult.records[0];
 		const nativeRecord = nativeResult.records[0];

 		const eavKeys = Object.keys(eavRecord).sort();
 		const nativeKeys = Object.keys(nativeRecord).sort();
+		expect(eavRecord._kind).toBe("record");
+		expect(nativeRecord._kind).toBe("native");
 		expect(eavKeys).toEqual(nativeKeys);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@convex/crm/__tests__/systemAdapters.test.ts` around lines 334 - 447, The test
currently only compares keys; add explicit assertions for the discriminator
values by checking eavRecord._kind equals the expected EAV discriminator (e.g.,
"eav") and nativeRecord._kind equals the expected native discriminator (e.g.,
"native") before or after the existing key comparisons; locate the assertions
around where eavRecord and nativeRecord are defined in the "EAV and native
records have identical UnifiedRecord keys" test (references: eavResult,
nativeResult, eavRecord, nativeRecord, and api.crm.recordQueries.queryRecords)
and add two expect(...) checks that assert the exact _kind string values.

114-320: Add smoke coverage for the other queryNativeTable branches.

This suite only exercises the mortgages path through queryRecords. The remaining switch arms (borrowers, lenders, brokers, deals, obligations) and the unknown-table failure path stay untested, so a typo in one branch can still ship while this suite stays green. A small it.each(...) smoke suite, or one direct queryNativeTable test for the default/error branch, would close that gap.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@convex/crm/__tests__/systemAdapters.test.ts` around lines 114 - 320, The
tests only cover the "mortgages" branch of queryNativeTable; add a small smoke
test that bootstraps system objects
(internal.crm.systemAdapters.bootstrap.bootstrapSystemObjects), then iterates
(it.each) over the remaining native table names
("borrowers","lenders","brokers","deals","obligations") to locate each objectDef
by name and call api.crm.recordQueries.queryRecords (via asAdmin(t)) with that
objectDefId, asserting the call returns without error and yields records of
_kind "native" (or at least a records array); also add one test that
constructs/queries with a bogus/unknown objectDef (or directly calls
queryNativeTable with an invalid table name) and asserts the default/error
branch is exercised (throws or returns the expected error) to cover the
unknown-table path.
convex/crm/__tests__/viewEngine.test.ts (1)

78-85: Consider reducing type assertion verbosity.

The test file uses numerous inline type assertions throughout (e.g., result as { columns: Array<{...}>, rows: Array<{...}> }). While these assertions work correctly, they're verbose and repetitive. Consider one of these approaches:

  1. Define shared result types at the top of the file for common response shapes (e.g., TableViewResult, KanbanViewResult, CalendarViewResult).
  2. Improve API return type inference by ensuring the production query functions have explicit, exported return types that TypeScript can infer in tests.
  3. Use type helper utilities to extract and reuse common patterns.

Example refactor:

// At top of file
type TableViewResult = {
  columns: Array<{ name: string; displayOrder: number; isVisible: boolean }>;
  rows: Array<{ fields: Record<string, unknown> }>;
  cursor: string | null;
  totalCount: number;
};

// In test
const result = await asAdmin(t).query(...) as TableViewResult;

This would reduce duplication and improve maintainability.

Also applies to: 120-123, 159-163, 178-182, 224-231, 264-269, 299-305, 361-367, 405-411, 453-456, 497-500, 536-539

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@convex/crm/__tests__/viewEngine.test.ts` around lines 78 - 85, The test uses
repetitive inline type assertions (e.g., the local cast around result and
destructured columns/rows); define shared response types at the top of
conv​ex/crm/__tests__/viewEngine.test.ts (for example TableViewResult,
KanbanViewResult, CalendarViewResult matching the shapes used in tests) and
replace the inline assertions like "result as { columns: Array<...>; rows:
Array<...> }" with those named types, and/or export/consume the real query
return types from the production code so tests can use them (update test usages
of result, columns, rows and any asAdmin(...).query(...) casts to use the new
shared types to remove duplication and verbosity).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@convex/crm/__tests__/walkthrough.test.ts`:
- Around line 194-212: The test currently swallows all failures from the
asAdmin(t).query(api.crm.recordQueries.searchRecords, ...) call; replace the
bare catch with either an explicit feature check (e.g., call a helper like
isSearchIndexSupported()/feature flag before running the search assertion) or
inspect the thrown error and only skip when it matches the known "search index
not supported" sentinel (check error.message/code) while rethrowing other errors
so auth, schema, and logic failures surface; update the try/catch around the
search block (the asAdmin(t).query call and subsequent expect(...) checks) to
implement this targeted handling.

---

Nitpick comments:
In `@convex/crm/__tests__/systemAdapters.test.ts`:
- Around line 334-447: The test currently only compares keys; add explicit
assertions for the discriminator values by checking eavRecord._kind equals the
expected EAV discriminator (e.g., "eav") and nativeRecord._kind equals the
expected native discriminator (e.g., "native") before or after the existing key
comparisons; locate the assertions around where eavRecord and nativeRecord are
defined in the "EAV and native records have identical UnifiedRecord keys" test
(references: eavResult, nativeResult, eavRecord, nativeRecord, and
api.crm.recordQueries.queryRecords) and add two expect(...) checks that assert
the exact _kind string values.
- Around line 114-320: The tests only cover the "mortgages" branch of
queryNativeTable; add a small smoke test that bootstraps system objects
(internal.crm.systemAdapters.bootstrap.bootstrapSystemObjects), then iterates
(it.each) over the remaining native table names
("borrowers","lenders","brokers","deals","obligations") to locate each objectDef
by name and call api.crm.recordQueries.queryRecords (via asAdmin(t)) with that
objectDefId, asserting the call returns without error and yields records of
_kind "native" (or at least a records array); also add one test that
constructs/queries with a bogus/unknown objectDef (or directly calls
queryNativeTable with an invalid table name) and asserts the default/error
branch is exercised (throws or returns the expected error) to cover the
unknown-table path.

In `@convex/crm/__tests__/viewEngine.test.ts`:
- Around line 78-85: The test uses repetitive inline type assertions (e.g., the
local cast around result and destructured columns/rows); define shared response
types at the top of conv​ex/crm/__tests__/viewEngine.test.ts (for example
TableViewResult, KanbanViewResult, CalendarViewResult matching the shapes used
in tests) and replace the inline assertions like "result as { columns:
Array<...>; rows: Array<...> }" with those named types, and/or export/consume
the real query return types from the production code so tests can use them
(update test usages of result, columns, rows and any asAdmin(...).query(...)
casts to use the new shared types to remove duplication and verbosity).

In `@convex/crm/__tests__/walkthrough.test.ts`:
- Around line 169-192: After updating the record via
asAdmin(t).mutation(api.crm.records.updateRecord), re-query the kanban view by
calling asAdmin(t).query(api.crm.viewQueries.queryViewRecords, { viewDefId:
kanbanViewId, limit: 100 }) and assert the kanban buckets reflect the move
(e.g., find the bucket for status "New" and "contacted" in the returned rows or
grouping metadata and verify the count for "New" decreased and "contacted"
increased compared to the pre-update values); use the same approach you used for
tableViewId (tableResult/updatedTable) but target kanbanViewId and compare
counts to ensure the board regrouped after the status change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d44bfe8d-0337-4ed0-8188-1facf6686e7a

📥 Commits

Reviewing files that changed from the base of the PR and between 71568a9 and ae2181e.

📒 Files selected for processing (17)
  • convex/crm/__tests__/helpers.ts
  • convex/crm/__tests__/links.test.ts
  • convex/crm/__tests__/metadataCompiler.test.ts
  • convex/crm/__tests__/records.test.ts
  • convex/crm/__tests__/systemAdapters.test.ts
  • convex/crm/__tests__/viewEngine.test.ts
  • convex/crm/__tests__/walkthrough.test.ts
  • specs/ENG-260/chunks/chunk-01-helpers-metadata/context.md
  • specs/ENG-260/chunks/chunk-01-helpers-metadata/tasks.md
  • specs/ENG-260/chunks/chunk-02-record-crud/context.md
  • specs/ENG-260/chunks/chunk-02-record-crud/tasks.md
  • specs/ENG-260/chunks/chunk-03-view-engine/context.md
  • specs/ENG-260/chunks/chunk-03-view-engine/tasks.md
  • specs/ENG-260/chunks/chunk-04-adapters-links-walkthrough/context.md
  • specs/ENG-260/chunks/chunk-04-adapters-links-walkthrough/tasks.md
  • specs/ENG-260/chunks/manifest.md
  • specs/ENG-260/tasks.md

Comment thread convex/crm/__tests__/walkthrough.test.ts
Connorbelez and others added 5 commits March 31, 2026 10:13
… FieldSeedConfig

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…kthrough test

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…nbanRecord

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@convex/crm/__tests__/viewEngine.test.ts`:
- Around line 643-674: The test "gte/lte filter: inclusive numeric range" only
inserts a gte filter (in the t.run insert into viewFilters using operator "gte")
but never exercises lte; either add a second insert that uses operator "lte"
(e.g., insert an lte filter for the same fieldDefId with value
JSON.stringify(200_000) and assert totalCount equals expected single record or
appropriate combined-range count when querying via asAdmin(...
api.crm.viewQueries.queryViewRecords ...)) or rename the test to "gte filter:
inclusive numeric range" to match the current behavior; update assertions
accordingly and keep references to seedLeadFixture, seedRecord, the viewFilters
insert, and the asAdmin query when making the change.
- Around line 884-891: The test is asserting the wrong audit action: when
calling moveKanbanRecord the system emits "crm.record.fieldUpdated" but the test
searches for "crm.record.updated"; update the assertion in the test (around
auditEntries/queryByResource and the updateEntry find) to look for action ===
"crm.record.fieldUpdated" (and keep the same existence/assertion logic) so the
audit lookup matches the actual event emitted by moveKanbanRecord.

In `@convex/crm/__tests__/walkthrough.test.ts`:
- Around line 210-218: The catch block that checks SEARCH_UNSUPPORTED_RE
currently calls return which aborts the test and skips the subsequent step-10
perf assertions; remove the early return in that catch (the block that tests
`error instanceof Error && SEARCH_UNSUPPORTED_RE.test(error.message)`) so it
only logs the warning via console.warn and allows the test to continue executing
the remaining steps (including the step-10 perf block).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e0ca9fc2-78ad-4504-ab98-28a924584067

📥 Commits

Reviewing files that changed from the base of the PR and between ae2181e and 1cb061c.

📒 Files selected for processing (5)
  • convex/crm/__tests__/helpers.ts
  • convex/crm/__tests__/records.test.ts
  • convex/crm/__tests__/systemAdapters.test.ts
  • convex/crm/__tests__/viewEngine.test.ts
  • convex/crm/__tests__/walkthrough.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • convex/crm/tests/systemAdapters.test.ts

Comment on lines +643 to +674
it("gte/lte filter: inclusive numeric range", async () => {
const fixture = await seedLeadFixture(t);

await seedRecord(t, fixture.objectDefId, {
company_name: "Exact",
deal_value: 200_000,
});
await seedRecord(t, fixture.objectDefId, {
company_name: "Below",
deal_value: 100_000,
});
await seedRecord(t, fixture.objectDefId, {
company_name: "Above",
deal_value: 300_000,
});

await t.run(async (ctx) => {
await ctx.db.insert("viewFilters", {
viewDefId: fixture.defaultViewId,
fieldDefId: fixture.fieldDefs.deal_value,
operator: "gte",
value: JSON.stringify(200_000),
});
});

const result = await asAdmin(t).query(
api.crm.viewQueries.queryViewRecords,
{ viewDefId: fixture.defaultViewId, limit: 25 }
);
const { totalCount } = result as { totalCount: number };
expect(totalCount).toBe(2); // Exact + Above
});
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.

⚠️ Potential issue | 🟡 Minor

gte/lte test currently exercises only gte.

The case name claims both operators, but only a gte filter is inserted/asserted. Either add an lte assertion path or rename this case to avoid false coverage signals.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@convex/crm/__tests__/viewEngine.test.ts` around lines 643 - 674, The test
"gte/lte filter: inclusive numeric range" only inserts a gte filter (in the
t.run insert into viewFilters using operator "gte") but never exercises lte;
either add a second insert that uses operator "lte" (e.g., insert an lte filter
for the same fieldDefId with value JSON.stringify(200_000) and assert totalCount
equals expected single record or appropriate combined-range count when querying
via asAdmin(... api.crm.viewQueries.queryViewRecords ...)) or rename the test to
"gte filter: inclusive numeric range" to match the current behavior; update
assertions accordingly and keep references to seedLeadFixture, seedRecord, the
viewFilters insert, and the asAdmin query when making the change.

Comment on lines +884 to +891
// Audit: verify crm.record.updated event was emitted
const auditEntries = await t.query(
components.auditLog.lib.queryByResource,
{ resourceType: "records", resourceId: recordId }
);
const updateEntry = auditEntries.find(
(e: { action: string }) => e.action === "crm.record.updated"
);
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.

⚠️ Potential issue | 🟠 Major

Audit assertion uses the wrong action name for moveKanbanRecord.

moveKanbanRecord emits crm.record.fieldUpdated, but this test searches for crm.record.updated, so it can fail even when behavior is correct.

Suggested patch
 			const updateEntry = auditEntries.find(
-				(e: { action: string }) => e.action === "crm.record.updated"
+				(e: { action: string }) => e.action === "crm.record.fieldUpdated"
 			);
 			expect(updateEntry).toBeDefined();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@convex/crm/__tests__/viewEngine.test.ts` around lines 884 - 891, The test is
asserting the wrong audit action: when calling moveKanbanRecord the system emits
"crm.record.fieldUpdated" but the test searches for "crm.record.updated"; update
the assertion in the test (around auditEntries/queryByResource and the
updateEntry find) to look for action === "crm.record.fieldUpdated" (and keep the
same existence/assertion logic) so the audit lookup matches the actual event
emitted by moveKanbanRecord.

Comment on lines +210 to +218
} catch (error) {
// Only treat explicit "search not supported" errors as a reason to skip.
if (error instanceof Error && SEARCH_UNSUPPORTED_RE.test(error.message)) {
// convex-test may not support search indexes — skip gracefully
console.warn(
"Search index not supported in convex-test — skipping search assertion"
);
return;
}
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.

⚠️ Potential issue | 🟡 Minor

Avoid returning early from the unsupported-search catch path.

At Line 217, return exits the test and skips the step-10 perf block entirely. Prefer warning and continuing so the rest of the walkthrough still runs when search indexes are unavailable.

Suggested patch
 		} catch (error) {
 			// Only treat explicit "search not supported" errors as a reason to skip.
 			if (error instanceof Error && SEARCH_UNSUPPORTED_RE.test(error.message)) {
 				// convex-test may not support search indexes — skip gracefully
 				console.warn(
 					"Search index not supported in convex-test — skipping search assertion"
 				);
-				return;
+				// continue test; only skip the search assertion itself
 			}
 			// Unexpected error — surface it instead of silently skipping.
 			throw error;
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@convex/crm/__tests__/walkthrough.test.ts` around lines 210 - 218, The catch
block that checks SEARCH_UNSUPPORTED_RE currently calls return which aborts the
test and skips the subsequent step-10 perf assertions; remove the early return
in that catch (the block that tests `error instanceof Error &&
SEARCH_UNSUPPORTED_RE.test(error.message)`) so it only logs the warning via
console.warn and allows the test to continue executing the remaining steps
(including the step-10 perf block).

@Connorbelez Connorbelez merged commit b04f4ee into main Mar 31, 2026
1 of 3 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Mar 31, 2026
This was referenced Apr 9, 2026
Connorbelez added a commit that referenced this pull request Apr 20, 2026
eng-260

eng-260

## Summary by Sourcery

Add comprehensive CRM EAV test harness and high-level specification docs, plus new integration tests for the view engine and native system adapters.

Documentation:
- Add ENG-260 spec and chunk task/context documentation describing CRM test harness, record/view/system adapter behaviors, and planned link tests.

Tests:
- Introduce shared CRM convex-test harness with identities and seed helpers for objects, fields, and records.
- Add metadata compiler tests covering capability derivation and lifecycle on field create/update/deactivate.
- Add record CRUD tests validating value routing, validation, soft delete behavior, and audit logging.
- Add view engine tests for table, kanban, and calendar views, including filters, pagination, schema, integrity, and Kanban moves.
- Add system adapter tests for native table querying, column resolution, and UnifiedRecord parity between EAV and native records.
- Add an end-to-end CRM walkthrough test covering object/field setup, views, records, grouping, and search, plus scaffolding for future link tests.

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

* **Tests**
  * Added comprehensive test suites for CRM record management, including create, update, delete, and query operations across multiple field types.
  * Added view engine tests validating table, kanban, and calendar view functionality with filtering and sorting.
  * Added system adapter tests for native table integration and unified record handling.
  * Added end-to-end integration test covering the complete CRM workflow.

* **Documentation**
  * Added implementation guides and test context documentation for CRM features across four sequential specification chunks.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
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.

2 participants