|
| 1 | +(ns cmr.search.test.unit.services.query-execution.granule-counts-results-feature-test |
| 2 | + (:require |
| 3 | + [clojure.test :refer :all] |
| 4 | + [cmr.common.services.search.query-model :as q] |
| 5 | + [cmr.search.models.query :as qm] |
| 6 | + [cmr.search.services.query-execution.granule-counts-results-feature :as gcrf] |
| 7 | + [cmr.spatial.point :as p] |
| 8 | + [cmr.spatial.polygon :as poly] |
| 9 | + [cmr.spatial.geodetic-ring :as gr] |
| 10 | + [cmr.elastic-utils.search.es-group-query-conditions :as gc])) |
| 11 | + |
| 12 | +(defn- make-spatial-condition |
| 13 | + "Creates a SpatialCondition with a simple polygon" |
| 14 | + [lon lat] |
| 15 | + (let [points [(p/point lon lat) |
| 16 | + (p/point (+ lon 10) lat) |
| 17 | + (p/point (+ lon 10) (+ lat 10)) |
| 18 | + (p/point lon (+ lat 10)) |
| 19 | + (p/point lon lat)] |
| 20 | + ring (gr/ring points) |
| 21 | + polygon (poly/polygon :geodetic [ring])] |
| 22 | + (qm/->SpatialCondition polygon))) |
| 23 | + |
| 24 | +(deftest is-spatial-or-group-test |
| 25 | + (testing "Returns true for OR group of SpatialConditions" |
| 26 | + (let [cond1 (make-spatial-condition 10 0) |
| 27 | + cond2 (make-spatial-condition 44 -25) |
| 28 | + or-group (gc/or-conds [cond1 cond2])] |
| 29 | + (is (true? (#'gcrf/is-spatial-or-group? or-group))))) |
| 30 | + |
| 31 | + (testing "Returns false for AND group of SpatialConditions" |
| 32 | + (let [cond1 (make-spatial-condition 10 0) |
| 33 | + cond2 (make-spatial-condition 44 -25) |
| 34 | + and-group (gc/and-conds [cond1 cond2])] |
| 35 | + (is (false? (#'gcrf/is-spatial-or-group? and-group))))) |
| 36 | + |
| 37 | + (testing "Returns false for OR group with non-SpatialConditions" |
| 38 | + (let [cond1 (make-spatial-condition 10 0) |
| 39 | + cond2 (q/string-condition :entry-title "test") |
| 40 | + or-group (gc/or-conds [cond1 cond2])] |
| 41 | + (is (false? (#'gcrf/is-spatial-or-group? or-group))))) |
| 42 | + |
| 43 | + (testing "Returns false for single SpatialCondition" |
| 44 | + (let [cond1 (make-spatial-condition 10 0)] |
| 45 | + (is (false? (#'gcrf/is-spatial-or-group? cond1)))))) |
| 46 | + |
| 47 | +(deftest extract-spatial-conditions-preserves-or-groups-test |
| 48 | + (testing "Extracts OR group of SpatialConditions preserving structure" |
| 49 | + (let [cond1 (make-spatial-condition 10 0) |
| 50 | + cond2 (make-spatial-condition 44 -25) |
| 51 | + or-group (gc/or-conds [cond1 cond2]) |
| 52 | + query (q/query {:concept-type :collection |
| 53 | + :condition or-group}) |
| 54 | + result (gcrf/extract-spatial-conditions query)] |
| 55 | + (is (= [or-group] result)))) |
| 56 | + |
| 57 | + (testing "Extracts OR group nested with non-spatial conditions" |
| 58 | + (let [cond1 (make-spatial-condition 10 0) |
| 59 | + cond2 (make-spatial-condition 44 -25) |
| 60 | + or-group (gc/or-conds [cond1 cond2]) |
| 61 | + title-cond (q/string-condition :entry-title "test") |
| 62 | + provider-cond (q/string-condition :provider "PROV1") |
| 63 | + combined (gc/and-conds [title-cond or-group provider-cond]) |
| 64 | + query (q/query {:concept-type :collection |
| 65 | + :condition combined}) |
| 66 | + result (gcrf/extract-spatial-conditions query)] |
| 67 | + (is (= [or-group] result))))) |
| 68 | + |
| 69 | +(deftest extract-spatial-conditions-single-condition-test |
| 70 | + (testing "Extracts single SpatialCondition" |
| 71 | + (let [cond1 (make-spatial-condition 10 0) |
| 72 | + query (q/query {:concept-type :collection |
| 73 | + :condition cond1}) |
| 74 | + result (gcrf/extract-spatial-conditions query)] |
| 75 | + (is (= [cond1] result)))) |
| 76 | + |
| 77 | + (testing "Extracts single SpatialCondition nested with non-spatial conditions" |
| 78 | + (let [spatial-cond (make-spatial-condition 10 0) |
| 79 | + title-cond (q/string-condition :entry-title "test") |
| 80 | + provider-cond (q/string-condition :provider "PROV1") |
| 81 | + combined (gc/and-conds [title-cond spatial-cond provider-cond]) |
| 82 | + query (q/query {:concept-type :collection |
| 83 | + :condition combined}) |
| 84 | + result (gcrf/extract-spatial-conditions query)] |
| 85 | + (is (= [spatial-cond] result))))) |
| 86 | + |
| 87 | +(deftest extract-spatial-conditions-mixed-test |
| 88 | + (testing "Extracts both OR groups and ungrouped SpatialConditions" |
| 89 | + (let [cond1 (make-spatial-condition 10 0) |
| 90 | + cond2 (make-spatial-condition 44 -25) |
| 91 | + cond3 (make-spatial-condition 100 50) |
| 92 | + or-group (gc/or-conds [cond1 cond2]) |
| 93 | + combined (gc/and-conds [or-group cond3]) |
| 94 | + query (q/query {:concept-type :collection |
| 95 | + :condition combined}) |
| 96 | + result (gcrf/extract-spatial-conditions query)] |
| 97 | + (is (= [or-group cond3] result)))) |
| 98 | + |
| 99 | + (testing "Extracts OR groups and ungrouped conditions with non-spatial conditions mixed in" |
| 100 | + (let [cond1 (make-spatial-condition 10 0) |
| 101 | + cond2 (make-spatial-condition 44 -25) |
| 102 | + cond3 (make-spatial-condition 100 50) |
| 103 | + or-group (gc/or-conds [cond1 cond2]) |
| 104 | + title-cond (q/string-condition :entry-title "test") |
| 105 | + provider-cond (q/string-condition :provider "PROV1") |
| 106 | + combined (gc/and-conds [title-cond or-group provider-cond cond3]) |
| 107 | + query (q/query {:concept-type :collection |
| 108 | + :condition combined}) |
| 109 | + result (gcrf/extract-spatial-conditions query)] |
| 110 | + (is (= [or-group cond3] result))))) |
| 111 | + |
| 112 | +(deftest extract-spatial-conditions-empty-test |
| 113 | + (testing "Returns empty list when no spatial conditions" |
| 114 | + (let [cond1 (q/string-condition :entry-title "test") |
| 115 | + query (q/query {:concept-type :collection |
| 116 | + :condition cond1}) |
| 117 | + result (gcrf/extract-spatial-conditions query)] |
| 118 | + (is (= [] result)))) |
| 119 | + |
| 120 | + (testing "Returns empty list when only non-spatial conditions" |
| 121 | + (let [title-cond (q/string-condition :entry-title "test") |
| 122 | + provider-cond (q/string-condition :provider "PROV1") |
| 123 | + combined (gc/and-conds [title-cond provider-cond]) |
| 124 | + query (q/query {:concept-type :collection |
| 125 | + :condition combined}) |
| 126 | + result (gcrf/extract-spatial-conditions query)] |
| 127 | + (is (= [] result))))) |
| 128 | + |
| 129 | +(deftest extract-spatial-conditions-with-duplicate-polygon-test |
| 130 | + (testing "Extracts both OR group and standalone duplicate SpatialCondition" |
| 131 | + (let [cond1 (make-spatial-condition 10 0) |
| 132 | + cond2 (make-spatial-condition 44 -25) |
| 133 | + cond3 (make-spatial-condition 10 0) |
| 134 | + or-group (gc/or-conds [cond1 cond2]) |
| 135 | + combined (gc/and-conds [or-group cond3]) |
| 136 | + query (q/query {:concept-type :collection |
| 137 | + :condition combined}) |
| 138 | + result (gcrf/extract-spatial-conditions query)] |
| 139 | + (is (= [or-group cond3] result))))) |
| 140 | + |
| 141 | +(deftest extract-spatial-conditions-validates-parent-path-test |
| 142 | + (testing "Rejects SpatialCondition under NegatedCondition" |
| 143 | + (let [spatial-cond (make-spatial-condition 10 0) |
| 144 | + negated (q/negated-condition spatial-cond) |
| 145 | + query (q/query {:concept-type :collection |
| 146 | + :condition negated})] |
| 147 | + (is (thrown? Exception |
| 148 | + (gcrf/extract-spatial-conditions query))))) |
| 149 | + |
| 150 | + (testing "Rejects SpatialCondition nested under NegatedCondition in AND group" |
| 151 | + (let [spatial-cond (make-spatial-condition 10 0) |
| 152 | + title-cond (q/string-condition :entry-title "test") |
| 153 | + negated (q/negated-condition spatial-cond) |
| 154 | + combined (gc/and-conds [title-cond negated]) |
| 155 | + query (q/query {:concept-type :collection |
| 156 | + :condition combined})] |
| 157 | + (is (thrown? Exception |
| 158 | + (gcrf/extract-spatial-conditions query))))) |
| 159 | + |
| 160 | + (testing "Accepts valid SpatialCondition in AND group" |
| 161 | + (let [spatial-cond (make-spatial-condition 10 0) |
| 162 | + title-cond (q/string-condition :entry-title "test") |
| 163 | + combined (gc/and-conds [title-cond spatial-cond]) |
| 164 | + query (q/query {:concept-type :collection |
| 165 | + :condition combined})] |
| 166 | + (is (seq (gcrf/extract-spatial-conditions query))))) |
| 167 | + |
| 168 | + (testing "Accepts valid SpatialCondition at top level" |
| 169 | + (let [spatial-cond (make-spatial-condition 10 0) |
| 170 | + query (q/query {:concept-type :collection |
| 171 | + :condition spatial-cond})] |
| 172 | + (is (seq (gcrf/extract-spatial-conditions query))))) |
| 173 | + |
| 174 | + (testing "Preserves MultiPolygon OR groups with validation" |
| 175 | + (let [spatial-cond-1 (make-spatial-condition 10 0) |
| 176 | + spatial-cond-2 (make-spatial-condition 20 10) |
| 177 | + or-group (gc/or-conds [spatial-cond-1 spatial-cond-2]) |
| 178 | + query (q/query {:concept-type :collection |
| 179 | + :condition or-group})] |
| 180 | + (is (= [or-group] (gcrf/extract-spatial-conditions query)))))) |
0 commit comments