---
module: accounts test module
date: 2026-02-06
problem_type: test_failure
component: clojure_test
symptoms:
  - "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"
root_cause: incorrect_destructuring_patterns_and_parameter_formats
severity: medium
tags: [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:
```clojure
(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:
```clojure
(: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:

```clojure
;; 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:

```clojure
;; 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:

```clojure
;; 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:

```clojure
;; 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] ...)
```
