---
title: "Add comprehensive tests for SSR admin transaction rules module"
type: feat
date: 2026-02-07
component: auto-ap.ssr.admin.transaction-rules
tags: [testing, ssr, transaction-rules, rules-engine, bdd]
---

# Add Comprehensive Tests for SSR Admin Transaction Rules Module

## Overview

Add comprehensive BDD-style tests for the SSR admin transaction rules module (`src/clj/auto_ap/ssr/admin/transaction_rules.clj`). The transaction rules module is a **1,012-line critical component** that enables automated transaction categorization through rule-based matching. Unlike the vendors module, transaction rules includes a sophisticated rule-matching engine that finds and applies rules to transactions.

## Problem Statement

The transaction rules module currently has **zero tests** despite being a critical 1,012-line component with complex functionality:

1. **Rule matching engine** - Matches transactions based on description, amount, day-of-month, client-group, bank-account
2. **Test/Preview functionality** - Shows matching transactions before execution
3. **Execute functionality** - Applies rules to matching transactions with audit logging
4. **Multi-step wizard** - For creating/editing transaction rules
5. **Complex filtering** - Regex pattern matching for notes, description includes, client-groups

This creates risks:
- **Untested rule matching logic** - Complex query building for transaction matching
- **No safety net for refactors** - Rule execution affects financial data
- **No documentation of expected behavior** - Tests serve as executable documentation
- **Risk of regression** - Changes to rule matching could silently break categorization

## Key Differences from Vendors Module

**Transaction Rules is MORE COMPLEX than vendors:**

| Feature | Vendors | Transaction Rules |
|---------|---------|-------------------|
| Lines of code | 932 | 1,012 |
| Grid operations | ✅ | ✅ |
| Multi-step wizard | ✅ (5 steps) | ✅ (Edit/Test modes) |
| **Rule matching engine** | ❌ | ✅ |
| **Test/Preview functionality** | ❌ | ✅ |
| **Execute/Apply functionality** | ❌ | ✅ |
| **Regex pattern matching** | ❌ | ✅ |
| **Transaction modification** | ❌ | ✅ |

**Unique transaction rules functionality to test:**
- `transactions-matching-rule` - Finds transactions matching rule criteria
- `transaction-rule-test-table*` - Preview matching transactions
- `execute` - Applies rules to transactions with audit logging
- Complex filtering by description patterns, amount ranges, day-of-month

## Proposed Solution

Create a comprehensive test suite at `test/clj/auto_ap/ssr/admin/transaction_rules_test.clj` following established patterns from `vendors_test.clj` and `accounts_test.clj`, with additional tests for the unique rule-matching functionality.

## Technical Considerations

### Architecture Impact
- Tests will mirror the vendors test structure
- Additional complexity: rule matching requires transaction test data
- Tests will use same utilities: `wrap-setup`, `admin-token`, `setup-test-data`
- Will need to mock Solr indexing like accounts tests do

### Performance Implications
- Rule matching queries are more complex than vendor queries
- Tests should verify both matching logic AND performance characteristics
- Each test should be independent with proper setup/teardown
- Estimated 18-22 tests (more than vendors due to rule engine complexity)

### Security Considerations
- Admin-only access verification
- Rule execution modifies transaction data (audit logging required)
- Non-admin access should be rejected
- JWT validation for rule operations

### Testing Challenges
1. **Rule matching complexity** - Multiple criteria (description, amount, bank-account, etc.)
2. **Test data dependencies** - Need transactions to test rule matching
3. **Regex pattern matching** - Testing pattern-based description matching
4. **Execute functionality** - Tests modify transaction data (need cleanup verification)
5. **Day-of-month filtering** - Date-based testing complexity

## Acceptance Criteria

### Functional Requirements

#### Grid & List View Tests (5 tests)

- [ ] **Test 1**: Transaction rule grid loads and displays rules
  - Given: Test transaction rules exist in database
  - When: Admin navigates to transaction rules page
  - Then: Rule table displays with correct columns (description, note, vendor, client)

- [ ] **Test 2**: Transaction rule grid filtering by vendor works
  - Given: Multiple rules with different vendors
  - When: Admin filters by specific vendor
  - Then: Only rules for that vendor are displayed

- [ ] **Test 3**: Transaction rule grid filtering by note pattern works
  - Given: Rules with different note patterns
  - When: Admin filters by note regex pattern
  - Then: Only matching rules are displayed

- [ ] **Test 4**: Transaction rule grid filtering by description works
  - Given: Rules with different descriptions
  - When: Admin filters by description substring
  - Then: Only matching rules are displayed

- [ ] **Test 5**: Transaction rule grid sorting works
  - Given: Multiple transaction rules
  - When: Admin sorts by description, note, or amount
  - Then: Rules are sorted correctly

#### Rule Matching Engine Tests (6 tests) - **UNIQUE TO TRANSACTION RULES**

- [ ] **Test 6**: Rule matching by description pattern works
  - Given: Transaction with description "HOME DEPOT #1234"
  - When: Rule has description pattern "HOME DEPOT"
  - Then: Transaction matches the rule

- [ ] **Test 7**: Rule matching by amount range works
  - Given: Transaction with amount $150.00
  - When: Rule has amount-gte $100 and amount-lte $200
  - Then: Transaction matches the rule

- [ ] **Test 8**: Rule matching by bank account works
  - Given: Transaction from specific bank account
  - When: Rule specifies that bank account
  - Then: Transaction matches the rule

- [ ] **Test 9**: Rule matching by client group works
  - Given: Transaction for client in group "NTG"
  - When: Rule specifies client-group "NTG"
  - Then: Transaction matches the rule

- [ ] **Test 10**: Rule matching by day-of-month works
  - Given: Transaction on day 15 of month
  - When: Rule has dom-gte 10 and dom-lte 20
  - Then: Transaction matches the rule

- [ ] **Test 11**: Rule matching combines multiple criteria
  - Given: Transaction matching multiple criteria
  - When: Rule has description + amount + bank account criteria
  - Then: Transaction only matches if ALL criteria match

#### Rule Test/Preview Tests (3 tests) - **UNIQUE TO TRANSACTION RULES**

- [ ] **Test 12**: Rule test shows matching transactions
  - Given: Rule that matches 5 transactions
  - When: Admin previews the rule
  - Then: All 5 matching transactions are displayed

- [ ] **Test 13**: Rule test respects only-uncoded filter
  - Given: Rule matches 3 coded and 2 uncoded transactions
  - When: Admin previews with only-uncoded flag
  - Then: Only 2 uncoded transactions are shown

- [ ] **Test 14**: Rule test shows correct transaction details
  - Given: Matching transaction with specific details
  - When: Rule test displays results
  - Then: Transaction shows client, bank, date, description correctly

#### Rule Execution Tests (4 tests) - **UNIQUE TO TRANSACTION RULES**

- [ ] **Test 15**: Rule execution applies to matching transactions
  - Given: Rule matches 3 uncoded transactions
  - When: Admin executes the rule
  - Then: All 3 transactions are updated with rule's accounts
  - Then: Audit log records the changes
  - Then: Solr index is updated for modified transactions

- [ ] **Test 16**: Rule execution respects selected transaction IDs
  - Given: Rule matches 5 transactions
  - When: Admin selects only 2 specific transaction IDs to apply
  - Then: Only those 2 transactions are updated

- [ ] **Test 17**: Rule execution skips locked transactions
  - Given: Rule matches 3 transactions, 1 is locked
  - When: Admin executes the rule
  - Then: Only 2 unlocked transactions are updated

- [ ] **Test 18**: Rule execution validates before applying
  - Given: Invalid rule or locked transactions
  - When: Admin attempts execution
  - Then: Appropriate validation errors are shown

#### Rule Creation/Update Tests (3 tests)

- [ ] **Test 19**: Admin successfully creates transaction rule
  - Given: Admin is logged in with valid token
  - When: Admin submits rule creation form
  - Then: Rule is created successfully
  - Then: Rule appears in database

- [ ] **Test 20**: Rule creation validation works
  - Given: Admin submits form with invalid data
  - When: Validation runs
  - Then: Validation errors shown
  - Then: No rule is created

- [ ] **Test 21**: Existing rule can be updated
  - Given: Transaction rule exists in database
  - When: Admin edits and saves rule
  - Then: Changes are persisted
  - Then: Solr index is updated

#### Security Tests (2 tests)

- [ ] **Test 22**: Non-admin cannot create transaction rule
  - Given: Non-admin user token
  - When: User attempts to create rule
  - Then: Request is rejected (403 Forbidden)

- [ ] **Test 23**: Non-admin cannot execute rules
  - Given: Non-admin user token
  - When: User attempts to execute rule
  - Then: Request is rejected

### Non-Functional Requirements

- [ ] Tests use `wrap-setup` fixture for database isolation
- [ ] Tests use `admin-token` utility for authentication
- [ ] Solr is mocked using `with-redefs` with `InMemSolrClient`
- [ ] Test execution time < 3 seconds per test
- [ ] All tests pass with `lein test auto-ap.ssr.admin.transaction-rules-test`

### Quality Gates

- [ ] 23 tests implemented and passing
- [ ] Test coverage > 75% for transaction rule handlers
- [ ] Code formatted with `lein cljfmt check`
- [ ] No debug statements (`println`, `alog/peek`) in tests
- [ ] All `deftest` blocks at column 0 (consistent structure)

## Implementation Plan

### Phase 1: Foundation & Grid Tests (3 hours)

**Tasks:**

1. [ ] Review transaction_rules module structure
   - Read `src/clj/auto_ap/ssr/admin/transaction_rules.clj`
   - Identify key functions: `fetch-ids`, `hydrate-results`, `fetch-page`
   - Identify unique functions: `transactions-matching-rule`, `execute`, `transaction-rule-test-table*`
   - Understand rule schema and validation

2. [ ] Review reference tests
   - Read `vendors_test.clj` for grid test patterns
   - Read `accounts_test.clj` for save/update patterns
   - Note Datomic query patterns

3. [ ] Create test file structure
   - Create `test/clj/auto_ap/ssr/admin/transaction_rules_test.clj`
   - Set up namespace with required imports
   - Add `wrap-setup` fixture
   - Create helper for transaction rule test data

4. [ ] Implement Grid/List Tests 1-5

**Deliverable:** Test file with grid tests passing

### Phase 2: Rule Matching Engine Tests (4 hours)

5. [ ] Implement Test 6: Rule matching by description pattern
6. [ ] Implement Test 7: Rule matching by amount range
7. [ ] Implement Test 8: Rule matching by bank account
8. [ ] Implement Test 9: Rule matching by client group
9. [ ] Implement Test 10: Rule matching by day-of-month
10. [ ] Implement Test 11: Combined criteria matching

**Deliverable:** 6 rule matching tests passing

### Phase 3: Rule Test/Preview Tests (2.5 hours)

11. [ ] Implement Test 12: Rule test shows matching transactions
12. [ ] Implement Test 13: Rule test respects only-uncoded filter
13. [ ] Implement Test 14: Rule test shows correct details

**Deliverable:** 3 rule preview tests passing

### Phase 4: Rule Execution Tests (3 hours)

14. [ ] Implement Test 15: Rule execution applies to matching transactions
15. [ ] Implement Test 16: Rule execution respects selected IDs
16. [ ] Implement Test 17: Rule execution skips locked transactions
17. [ ] Implement Test 18: Rule execution validation

**Deliverable:** 4 rule execution tests passing

### Phase 5: Rule CRUD & Security (2.5 hours)

18. [ ] Implement Test 19: Rule creation success
19. [ ] Implement Test 20: Rule creation validation
20. [ ] Implement Test 21: Rule update
21. [ ] Implement Test 22: Non-admin cannot create
22. [ ] Implement Test 23: Non-admin cannot execute

**Deliverable:** 5 CRUD and security tests passing

### Phase 6: Refinement & Quality (1 hour)

23. [ ] Run `lein cljfmt check` and fix issues
24. [ ] Run full test suite
25. [ ] Review for debug statements and remove
26. [ ] Verify consistent test structure (deftest at column 0)
27. [ ] Add test documentation comments

**Deliverable:** All 23 tests passing, code formatted, no debug code

## Success Metrics

- [ ] 23 BDD test scenarios implemented and passing
- [ ] Test file follows project conventions
- [ ] Code formatted with `lein cljfmt check`
- [ ] All tests use proper Datomic query patterns (`ffirst`, `[:db/ident]`)
- [ ] Solr mocking works correctly
- [ ] Tests run in < 90 seconds for full suite
- [ ] No regression in existing functionality

## Dependencies & Risks

### Prerequisites

- `src/clj/auto_ap/ssr/admin/transaction_rules.clj` (exists)
- `test/clj/auto_ap/integration/util.clj` (test utilities)
- Existing vendors/accounts tests as reference pattern
- Datomic database schema for transaction rules
- Understanding of `auto-ap.rule-matching` namespace

### Potential Risks

1. **Complexity Risk**: Rule matching engine has complex query building
   - **Mitigation**: Test each criterion independently first, then test combinations

2. **Time Risk**: 23 tests may take longer than estimated
   - **Mitigation**: Prioritize rule matching and execution tests (core functionality)

3. **Test Data Risk**: Rule matching requires realistic transaction data
   - **Mitigation**: Use `setup-test-data` with comprehensive transaction fixtures

4. **Date Testing Risk**: Day-of-month filtering is date-dependent
   - **Mitigation**: Use fixed test dates or mock date functions

## References & Research

### Internal References

**Transaction Rules Source Code**:
- `src/clj/auto_ap/ssr/admin/transaction_rules.clj` - Main implementation (1,012 lines)
  - `fetch-ids` - Query builder for transaction rule grid
  - `hydrate-results` - Data hydration for grid display
  - `fetch-page` - Grid pagination
  - `transactions-matching-rule` - **Core rule matching engine** (lines 301-379)
  - `transaction-rule-test-table*` - **Preview/test functionality** (lines 381-507)
  - `execute` - **Rule execution with audit logging** (lines 521-571)
  - `validate-transaction-rule` - Rule validation logic (lines 271-299)
  - EditModal and TestModal records for wizard functionality

**Test Utilities**:
- `test/clj/auto_ap/integration/util.clj` - Test helpers
  - `wrap-setup` - Test database setup/teardown
  - `admin-token` - Admin authentication
  - `setup-test-data` - Test data creation
  - `test-transaction` - Transaction test data helper

**Reference Tests**:
- `test/clj/auto_ap/ssr/admin/vendors_test.clj` - Vendors test pattern (178 lines)
- `test/clj/auto_ap/ssr/admin/accounts_test.clj` - Accounts test pattern (151 lines)

**Rule Matching Engine**:
- `src/clj/auto_ap/rule_matching.clj` - Rule application logic
  - `apply-rule` - Applies rule to transaction
  - `rule-applies?` - Checks if rule matches transaction

### Testing Patterns

**Datomic Query Pattern**:
```clojure
; Use ffirst to extract entity ID from tuple
(let [results (dc/q '[:find ?e :where [?e :transaction-rule/description "Test"]] db)
      rule-id (ffirst results)]  ; Not (first results)
  ...)
```

**Entity Reference Resolution**:
```clojure
; Include [:db/ident] to resolve enum values
(let [rule (dc/pull db
                    '[:transaction-rule/description
                      {[:transaction-rule/transaction-approval-status :xform iol-ion.query/ident] [:db/ident]}]
                    rule-id)]
  ; Access as: (:db/ident (:transaction-rule/transaction-approval-status rule))
  ...)
```

**Solr Mocking Pattern**:
```clojure
(with-redefs [auto-ap.solr/impl (auto-ap.solr/->InMemSolrClient (atom {}))]
  ; Test code here
  )
```

**Test Structure Pattern**:
```clojure
(deftest transaction-rule-matching-by-description
  (testing "Rule should match transactions by description pattern"
    (with-redefs [auto-ap.solr/impl (auto-ap.solr/->InMemSolrClient (atom {}))]
      (let [admin-identity (admin-token)
            ; Test implementation
            ]))))
```

## AI-Era Considerations

When implementing with AI assistance:

1. **Accelerated test generation**: AI can generate test scaffolding quickly
2. **Pattern recognition**: Use existing vendors/accounts tests as templates
3. **Datomic patterns**: Ensure AI applies `ffirst` and `[:db/ident]` correctly
4. **Rule matching complexity**: Test each criterion independently before combinations
5. **Human review**: All AI-generated tests should be reviewed for:
   - Correct rule matching logic
   - Proper database verification
   - No debug statements left in
   - Consistent test structure

## Next Steps

1. **Review Plan**: Confirm scope and complexity level
2. **Start Implementation**: Begin with Phase 1 (Foundation & Grid Tests)
3. **Iterative Testing**: Implement tests incrementally, verify each phase
4. **Code Review**: Get feedback on test patterns
5. **Integration**: Ensure tests pass with full test suite

---

**Created**: 2026-02-07  
**Priority**: High (critical business functionality untested)  
**Estimated Effort**: 16 hours (across 6 phases)
