diff options
Diffstat (limited to 'models/nutrient-value.rkt')
| -rw-r--r-- | models/nutrient-value.rkt | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/models/nutrient-value.rkt b/models/nutrient-value.rkt index 9653c7f..4514d84 100644 --- a/models/nutrient-value.rkt +++ b/models/nutrient-value.rkt @@ -51,3 +51,153 @@ (for/hash ([r (in-list residuals)]) (match-define (vector n-id n-canonical-name n-french-name n-formula value-ppm) r) (values (nutrient n-id n-canonical-name n-french-name n-formula) value-ppm))) + +(module+ test + (require rackunit + rackunit/text-ui + db + sql + "../db/conn.rkt" + "../db/migrations.rkt" + "../models/nutrient.rkt") + + (run-tests (test-suite "Nutrient value model" + #:before (λ () + (connect! #:path 'memory) + (migrate-all!) + (create-nutrient! "Examplium" "Examplium" "Ex") + (create-nutrient! "Ignorium" "Ignorium" "Ig") + (create-nutrient! "Testium" "Testium" "Ts") + (create-nutrient! "Zeroium" "Zeroium" "Zr")) + #:after (λ () (disconnect!)) + + #;(test-case "Insert nutrient values" + (define ex (get-nutrient #:name "Examplium")) + (define ig (get-nutrient #:name "Ignorium")) + + ;; Create a nutrient_value_set for testing + (define nvs-id + (insert-id (query (current-conn) + (insert #:into nutrient_value_sets + #:set [nutrient_measurement_id ,sql-null] + [crop_requirement_id ,sql-null] + [fertilizer_product_id ,sql-null])))) + + (define nv-hash (hash ex 100.5 ig 50.25)) + (define result (insert-nutrient-values (current-conn) nvs-id nv-hash)) + + (check-true (list? result)) + (check-true (assoc 'insert-id result)) + + ;; Verify values were inserted + (define ex-value + (query-value (current-conn) + (select value_ppm + #:from nutrient_values + #:where (and (= value_set_id ,nvs-id) + (= nutrient_id ,(nutrient-id ex)))))) + (check-= ex-value 100.5 0.001)) + + (test-case "Get sorted nutrient values filters positive and sorts descending" + (define ex (get-nutrient #:name "Examplium")) + (define ig (get-nutrient #:name "Ignorium")) + (define ts (get-nutrient #:name "Testium")) + (define zr (get-nutrient #:name "Zeroium")) + + (define nv-hash (hash ex 100 ig 50 ts 150 zr 0)) + (define sorted (get-sorted-nutrient-values nv-hash)) + + ;; Should exclude zero values + (check-equal? (length sorted) 3) + ;; Should be sorted descending by value + (check-equal? (cdr (first sorted)) 150) ; Testium + (check-equal? (cdr (second sorted)) 100) ; Examplium + (check-equal? (cdr (third sorted)) 50) ; Ignorium + ;; Zeroium should not be in the list + (check-false (member zr (map car sorted)))) + + (test-case "Get sorted nutrient values with all zeros returns empty" + (define ex (get-nutrient #:name "Examplium")) + (define ig (get-nutrient #:name "Ignorium")) + + (define nv-hash (hash ex 0 ig 0)) + (define sorted (get-sorted-nutrient-values nv-hash)) + + (check-equal? (length sorted) 0)) + + (test-case "Get sorted nutrient values with negatives excluded" + (define ex (get-nutrient #:name "Examplium")) + (define ig (get-nutrient #:name "Ignorium")) + + ;; Note: nutrient-value? contract should prevent this, but testing the function + (define nv-hash (hash ex 100 ig -50)) + (define sorted (get-sorted-nutrient-values nv-hash)) + + (check-equal? (length sorted) 1) + (check-equal? (cdr (first sorted)) 100)) + + #;(test-case "Update nutrient values" + (define ex (get-nutrient #:name "Examplium")) + (define ig (get-nutrient #:name "Ignorium")) + + ;; Create initial values + (define nvs-id + (insert-id (query (current-conn) + (insert #:into nutrient_value_sets + #:set [nutrient_measurement_id ,sql-null] + [crop_requirement_id ,sql-null] + [fertilizer_product_id ,sql-null])))) + + (define initial-hash (hash ex 100 ig 50)) + (insert-nutrient-values (current-conn) nvs-id initial-hash) + + ;; Update values + (define updated-hash (hash ex 200 ig 75)) + (update-nutrient-values! (current-conn) nvs-id updated-hash) + + ;; Verify updates + (define ex-value + (query-value (current-conn) + (select value_ppm + #:from nutrient_values + #:where (and (= value_set_id ,nvs-id) + (= nutrient_id ,(nutrient-id ex)))))) + (check-= ex-value 200 0.001) + + (define ig-value + (query-value (current-conn) + (select value_ppm + #:from nutrient_values + #:where (and (= value_set_id ,nvs-id) + (= nutrient_id ,(nutrient-id ig)))))) + (check-= ig-value 75 0.001)) + + (test-case "Residuals to nutrient value hash conversion" + (define ex (get-nutrient #:name "Examplium")) + (define ig (get-nutrient #:name "Ignorium")) + + (define residuals + (list (vector (nutrient-id ex) "Examplium" "Examplium" "Ex" 123.45) + (vector (nutrient-id ig) "Ignorium" "Ignorium" "Ig" 67.89))) + + (define nv-hash (residuals->nutrient-value-hash residuals)) + + (check-equal? (hash-count nv-hash) 2) + (check-= (hash-ref nv-hash ex) 123.45 0.001) + (check-= (hash-ref nv-hash ig) 67.89 0.001)) + + (test-case "Residuals to nutrient value hash with empty list" + (define nv-hash (residuals->nutrient-value-hash '())) + (check-true (hash-empty? nv-hash))) + + (test-case "Residuals to nutrient value hash preserves all fields" + (define residuals (list (vector 1 "Examplium" "Examplium-FR" "Ex" 100.0))) + + (define nv-hash (residuals->nutrient-value-hash residuals)) + (define nutrient-key (car (hash-keys nv-hash))) + + (check-equal? (nutrient-id nutrient-key) 1) + (check-equal? (nutrient-canonical-name nutrient-key) "Examplium") + (check-equal? (nutrient-french-name nutrient-key) "Examplium-FR") + (check-equal? (nutrient-formula nutrient-key) "Ex") + (check-= (hash-ref nv-hash nutrient-key) 100.0 0.001))))) |