Files
integreat/docs/solutions/test-failures/test-destructuring-accounts-module-20260206.md
Bryce a7daf839ec feat(tests): Add comprehensive tests for SSR admin vendors module
Add 8 BDD-style tests for the vendors module covering grid/list
operations and vendor merge functionality. Tests follow established
patterns from accounts_test.clj and include proper database
verification.

Tests Implemented:
- vendor-grid-loads-with-empty-database
- vendor-fetch-ids-returns-correct-structure
- vendor-fetch-page-returns-vendors
- vendor-hydrate-results-works
- vendor-merge-transfers-references
- vendor-merge-same-vendor-rejected
- vendor-merge-invalid-vendor-handled
- vendor-hydration-includes-all-fields

Key Implementation Details:
- Uses setup-test-data helper with unique temp IDs
- Tests focus on public interface (fetch-page, merge-submit)
- Follows BDD Given/When/Then pattern
- All 8 tests passing (26 assertions)

Documentation:
- Created implementation plan in docs/plans/
- Documented solution patterns in docs/solutions/
- Created code review todos for future improvements

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-06 23:53:31 -08:00

8.4 KiB

module, date, problem_type, component, symptoms, root_cause, severity, tags
module date problem_type component symptoms root_cause severity tags
accounts test module 2026-02-06 test_failure clojure_test
matching-count is nil when destructuring fetch-page result
Form errors key expected [:account/numeric-code] but got :account/numeric-code
Unbound query variables: #{?sort-} when sorting by field
Tests failing with 3 failures and 4 errors
incorrect_destructuring_patterns_and_parameter_formats medium
destructuring
parameter_format
fetch_page
sort_parameters

Test Destructuring Issues in Accounts Module

Problem Description

Multiple tests in test/clj/auto_ap/ssr/admin/accounts_test.clj were failing due to incorrect destructuring patterns and parameter formats. Tests expected different return values and parameter structures than what the source code actually provides.

Observable Symptoms

FAIL in (account-creation-duplicate-numeric-code-detection)
expected: (contains? (:form-errors data) [:account/numeric-code])
  actual: (not (contains? #:account{:numeric-code ["The code 12347 is already in use."]} [:account/numeric-code]))

FAIL in (account-grid-view-loads-accounts)
expected: (number? matching-count)
  actual: (not (number? nil))

ERROR in (account-sorting-by-name)
Query is referencing unbound variables: #{?sort-}

Investigation Attempts

  1. Initial approach: Ran tests one at a time using lein test :only auto-ap.ssr.admin.accounts-test/[test-name]
  2. Discovered patterns: Found 3 distinct root causes affecting different test groups
  3. Checked source code: Reviewed accounts.clj to understand actual function signatures and parameter expectations

What didn't work:

  • Initially tried generic exception catching
  • Attempted to modify source code (wrong approach - should only fix tests)

Root Cause Analysis

Issue 1: Form Errors Key Format (account-creation-duplicate-numeric-code-detection)

Problem: Test expected vector key [:account/numeric-code]but actual form-errors map uses keyword key:account/numeric-code`.

Technical explanation: The field-validation-error function creates form-errors as (assoc-in {} path [m]) where path is [:account/numeric-code]. This creates a map with keyword key, not vector key.

Code location: src/clj/auto_ap/ssr/utils.clj - field-validation-error function creates the structure.

Issue 2: fetch-page Return Value Format (grid view and display tests)

Problem: Test destructured fetch-page result into 3-tuple [_ accounts matching-count] but function actually returns 2-tuple [accounts matching-count].

Technical explanation: The fetch-page function returns [results matching-count] where:

  • First element: array of account entities
  • Second element: total count (number)

Code location: src/clj/auto_ap/ssr/admin/accounts.clj line 143-148:

(defn fetch-page [request]
  (let [db (dc/db conn)
        {ids-to-retrieve :ids matching-count :count} (fetch-ids db request)]
    [(->> (hydrate-results ids-to-retrieve db request))
     matching-count]))

Issue 3: Sort Parameter Format (sorting tests)

Problem: Tests passed sort as string :sort "name" but add-sorter-fields expects collection of sort-keys.

Technical explanation: The add-sorter-fields function iterates over (:sort args) which should be a collection like [{:sort-key "name"}]. When passing a string, it fails to iterate properly.

Code location: src/clj/auto_ap/ssr/admin/accounts.clj line 100-106:

(:sort query-params) (add-sorter-fields {"name" ['[?e :account/name ?n]
                                          '[(clojure.string/upper-case ?n) ?sort-name]]
                                          "code" ['[(get-else $ ?e :account/numeric-code 0) ?sort-code]]
                                          "type" ['[?e :account/type ?t]
                                                  '[?t :db/ident ?ti]
                                                  '[(name ?ti) ?sort-type]]}
                                         query-params)

Working Solution

Fix 1: Form Errors Key Format

Changed in test/clj/auto_ap/ssr/admin/accounts_test.clj line 57:

;; BEFORE
(is (contains? (:form-errors data) [:account/numeric-code]))

;; AFTER
(is (contains? (:form-errors data) :account/numeric-code))

Fix 2: fetch-page Destructuring Pattern

Changed in test/clj/auto_ap/ssr/admin/accounts_test.clj lines 98-104 and 110-117:

;; BEFORE - expecting 3-tuple
(let [result (sut/fetch-page {:query-params {:page 1 :per-page 10}})
      [_ accounts matching-count] result]
  (is (vector? result))
  (is (= 2 (count result)))
  (is (number? matching-count)))

;; AFTER - proper 2-tuple destructuring
(let [[accounts matching-count] (sut/fetch-page {:query-params {:page 1 :per-page 10}})]
  (is (number? matching-count)))

Fix 3: Sort Parameter Format

Changed in test/clj/auto_ap/ssr/admin/accounts_test.clj lines 126 and 150:

;; BEFORE - passing string
{:query-params {:page 1 :per-page 10 :sort "name"}}

;; AFTER - passing collection with sort-keys
{:query-params {:page 1 :per-page 10 :sort [{:sort-key "name"}]}}

Files Modified

  • test/clj/auto_ap/ssr/admin/accounts_test.clj: Fixed 4 test functions
    • account-creation-duplicate-numeric-code-detection
    • account-grid-view-loads-accounts
    • account-grid-displays-correct-columns
    • account-sorting-by-name
    • account-sorting-by-type

Verification

Test results after fix:

Ran 9 tests containing 19 assertions.
0 failures, 0 errors.

All tests pass successfully.

Prevention Strategies

Destructuring Rules

  1. Always inspect function signatures before writing tests

    • Use (-> (sut/fetch-page ...) meta) or read source code to understand return types
    • Verify tuple lengths before destructuring
  2. Form errors follow a pattern

    • Look at how field-validation-error creates errors in utils.clj
    • Form errors use keyword keys, not vector keys
    • Pattern: (assoc-in {} path [message]) where path is keyword(s)
  3. Query parameters have specific formats

    • Sort parameters should be collections: [{:sort-key "field"}]
    • Check add-sorter-fields implementation in the source module
    • Don't assume single-value parameters when API accepts collections

Test-First Approach

  1. Mock/stub external dependencies in tests before calling functions

    • Always use with-redefs to control solr, database, etc.
    • This makes testing more predictable and isolated
  2. Run tests incrementally

    • Fix one test at a time using lein test :only
    • Track which tests fail to understand pattern
    • Don't fix multiple unrelated issues simultaneously

Pattern Recognition

Common destructuring issues to watch for:

Component Expected Format Common Mistake Fix
fetch-page [results matching-count] 3-tuple like [data pages total] Verify tuple length
Form errors {:field-name message} [:field-name message] Use keyword keys
Sort params [{:sort-key "field"}] "field" Use collection
Pagination {:page 1 :per-page 10} {:page 1} Provide all needed params

Cross-References

None - no similar issues found in existing documentation.

Lessons Learned

Key Patterns Extracted

  1. Never assume tuple sizes - Always verify return values match expectations
  2. Form error structure is consistent - Keyword keys, not vector keys
  3. Query parameter formats matter - Collections vs single values
  4. Inspect source code - The add-sorter-fields function reveals the expected sort parameter format
  5. Test incrementally - Run one test at a time to isolate issues

Debugging Process

When tests fail with "wrong number of arguments" or "destructuring failed":

  1. Check function signature in source code
  2. Add logging or print the actual return value (println "Result:" result)
  3. Verify parameter formats - especially collections
  4. Test incrementally - one failing test at a time

Documentation Reminder

Always document the actual API signature, not assumed ones:

;; BAD - assuming knowledge
(defn fetch-page [request] ...)  ; assumed return type

;; GOOD - verified from source
;; From accounts.clj:143-148
;; Returns: [results matching-count] where results is array of entities
(defn fetch-page [request] ...)