|
8 | 8 | from common.exceptions.service import MultipleActionsFound |
9 | 9 |
|
10 | 10 |
|
| 11 | +# --- parse_patterns --- |
| 12 | + |
| 13 | + |
| 14 | +@pytest.mark.unit |
| 15 | +def test_parse_patterns_none(): |
| 16 | + assert JourneyService.parse_patterns(None) == [] |
| 17 | + |
| 18 | + |
| 19 | +@pytest.mark.unit |
| 20 | +def test_parse_patterns_empty_string(): |
| 21 | + assert JourneyService.parse_patterns("") == [] |
| 22 | + |
| 23 | + |
| 24 | +@pytest.mark.unit |
| 25 | +def test_parse_patterns_comma_separated(): |
| 26 | + assert JourneyService.parse_patterns("a,b,c") == ["a", "b", "c"] |
| 27 | + |
| 28 | + |
| 29 | +@pytest.mark.unit |
| 30 | +def test_parse_patterns_newline_separated(): |
| 31 | + assert JourneyService.parse_patterns("a\nb\nc") == ["a", "b", "c"] |
| 32 | + |
| 33 | + |
| 34 | +@pytest.mark.unit |
| 35 | +def test_parse_patterns_trims_whitespace(): |
| 36 | + assert JourneyService.parse_patterns(" a , b ") == ["a", "b"] |
| 37 | + |
| 38 | + |
| 39 | +@pytest.mark.unit |
| 40 | +def test_parse_patterns_skips_empty_entries(): |
| 41 | + assert JourneyService.parse_patterns("a,,b") == ["a", "b"] |
| 42 | + |
| 43 | + |
| 44 | +# --- get_components_matching_patterns --- |
| 45 | + |
| 46 | + |
| 47 | +@pytest.mark.integration |
| 48 | +def test_get_components_matching_patterns_no_include_returns_empty(test_db, project, pipeline, pipeline_2): |
| 49 | + result = JourneyService.get_components_matching_patterns(str(project.id), [], []) |
| 50 | + assert result == [] |
| 51 | + |
| 52 | + |
| 53 | +@pytest.mark.integration |
| 54 | +def test_get_components_matching_patterns_wildcard_matches_all(test_db, project, pipeline, pipeline_2): |
| 55 | + result = JourneyService.get_components_matching_patterns(str(project.id), ["*"], []) |
| 56 | + assert {c.id for c in result} == {pipeline.id, pipeline_2.id} |
| 57 | + |
| 58 | + |
| 59 | +@pytest.mark.integration |
| 60 | +def test_get_components_matching_patterns_exact_key(test_db, project, pipeline, pipeline_2): |
| 61 | + result = JourneyService.get_components_matching_patterns(str(project.id), ["P1"], []) |
| 62 | + assert len(result) == 1 |
| 63 | + assert result[0].id == pipeline.id |
| 64 | + |
| 65 | + |
| 66 | +@pytest.mark.integration |
| 67 | +def test_get_components_matching_patterns_exclude_applied(test_db, project, pipeline, pipeline_2): |
| 68 | + result = JourneyService.get_components_matching_patterns(str(project.id), ["*"], ["P2"]) |
| 69 | + assert len(result) == 1 |
| 70 | + assert result[0].id == pipeline.id |
| 71 | + |
| 72 | + |
| 73 | +@pytest.mark.integration |
| 74 | +def test_get_components_matching_patterns_character_class_matches(test_db, project, pipeline, pipeline_2): |
| 75 | + # [pP]* matches both P1 and P2 regardless of case |
| 76 | + result = JourneyService.get_components_matching_patterns(str(project.id), ["[pP]*"], []) |
| 77 | + assert {c.id for c in result} == {pipeline.id, pipeline_2.id} |
| 78 | + |
| 79 | + |
| 80 | +@pytest.mark.integration |
| 81 | +def test_get_components_matching_patterns_character_class_negation(test_db, project, pipeline, pipeline_2): |
| 82 | + # [!pP]* excludes keys starting with p or P — neither P1 nor P2 should match |
| 83 | + result = JourneyService.get_components_matching_patterns(str(project.id), ["[!pP]*"], []) |
| 84 | + assert result == [] |
| 85 | + |
| 86 | + |
| 87 | +@pytest.mark.integration |
| 88 | +def test_get_components_matching_patterns_character_class_exclude(test_db, project, pipeline, pipeline_2): |
| 89 | + # include all, but exclude keys starting with p or P |
| 90 | + result = JourneyService.get_components_matching_patterns(str(project.id), ["*"], ["[pP]*"]) |
| 91 | + assert result == [] |
| 92 | + |
| 93 | + |
| 94 | +@pytest.mark.integration |
| 95 | +def test_get_components_matching_patterns_character_class_exclude_negation(test_db, project, pipeline, pipeline_2): |
| 96 | + # exclude *[!1] matches keys not ending in '1' — P2 is excluded, P1 remains |
| 97 | + result = JourneyService.get_components_matching_patterns(str(project.id), ["*"], ["*[!1]"]) |
| 98 | + assert len(result) == 1 |
| 99 | + assert result[0].id == pipeline.id |
| 100 | + |
| 101 | + |
| 102 | +@pytest.mark.integration |
| 103 | +def test_get_components_matching_patterns_question_mark_matches_any_single_char(test_db, project, pipeline, pipeline_2): |
| 104 | + # P? matches any key of exactly two chars starting with P — both P1 and P2 match |
| 105 | + result = JourneyService.get_components_matching_patterns(str(project.id), ["P?"], []) |
| 106 | + assert {c.id for c in result} == {pipeline.id, pipeline_2.id} |
| 107 | + |
| 108 | + |
| 109 | +@pytest.mark.integration |
| 110 | +def test_get_components_matching_patterns_question_mark_matches_specific(test_db, project, pipeline, pipeline_2): |
| 111 | + # ?1 matches any two-char key ending in '1' — only P1 matches |
| 112 | + result = JourneyService.get_components_matching_patterns(str(project.id), ["?1"], []) |
| 113 | + assert len(result) == 1 |
| 114 | + assert result[0].id == pipeline.id |
| 115 | + |
| 116 | + |
| 117 | +@pytest.mark.integration |
| 118 | +def test_get_components_matching_patterns_question_mark_exclude(test_db, project, pipeline, pipeline_2): |
| 119 | + # exclude ?1 removes P1, leaving P2 |
| 120 | + result = JourneyService.get_components_matching_patterns(str(project.id), ["*"], ["?1"]) |
| 121 | + assert len(result) == 1 |
| 122 | + assert result[0].id == pipeline_2.id |
| 123 | + |
| 124 | + |
| 125 | +@pytest.mark.integration |
| 126 | +def test_get_components_matching_patterns_only_own_project(test_db, project, pipeline, organization, user): |
| 127 | + from common.entities import Pipeline, Project |
| 128 | + |
| 129 | + other_project = Project.create(name="Other", organization=organization, created_by=user) |
| 130 | + Pipeline.create(name="Other P1", key="P1", project=other_project, created_by=user) |
| 131 | + result = JourneyService.get_components_matching_patterns(str(project.id), ["P1"], []) |
| 132 | + assert len(result) == 1 |
| 133 | + assert result[0].id == pipeline.id |
| 134 | + |
| 135 | + |
| 136 | +# --- apply_component_patterns --- |
| 137 | + |
| 138 | + |
| 139 | +@pytest.mark.integration |
| 140 | +def test_apply_component_patterns_no_include_clears_edges(test_db, journey, pipeline): |
| 141 | + JourneyDagEdge.create(journey=journey, left=None, right=pipeline) |
| 142 | + journey.component_include_patterns = None |
| 143 | + journey.component_exclude_patterns = None |
| 144 | + JourneyService.apply_component_patterns(journey) |
| 145 | + assert JourneyDagEdge.select().where(JourneyDagEdge.journey == journey).count() == 0 |
| 146 | + |
| 147 | + |
| 148 | +@pytest.mark.integration |
| 149 | +def test_apply_component_patterns_adds_matching_as_root_nodes(test_db, journey, pipeline, pipeline_2): |
| 150 | + journey.component_include_patterns = "*" |
| 151 | + journey.component_exclude_patterns = None |
| 152 | + JourneyService.apply_component_patterns(journey) |
| 153 | + edges = list(JourneyDagEdge.select().where(JourneyDagEdge.journey == journey)) |
| 154 | + assert len(edges) == 2 |
| 155 | + assert all(e.left_id is None for e in edges) |
| 156 | + |
| 157 | + |
| 158 | +@pytest.mark.integration |
| 159 | +def test_apply_component_patterns_preserves_existing_edges(test_db, journey, pipeline, pipeline_2): |
| 160 | + JourneyDagEdge.create(journey=journey, left=pipeline, right=pipeline_2) |
| 161 | + journey.component_include_patterns = "*" |
| 162 | + journey.component_exclude_patterns = None |
| 163 | + JourneyService.apply_component_patterns(journey) |
| 164 | + edges = list(JourneyDagEdge.select().where(JourneyDagEdge.journey == journey)) |
| 165 | + # pipeline is root (no predecessor); pipeline->pipeline_2 edge is restored; pipeline_2 gets no root entry |
| 166 | + assert len(edges) == 2 |
| 167 | + root_edges = [e for e in edges if e.left_id is None] |
| 168 | + assert len(root_edges) == 1 |
| 169 | + assert root_edges[0].right_id == pipeline.id |
| 170 | + |
| 171 | + |
| 172 | +@pytest.mark.integration |
| 173 | +def test_apply_component_patterns_drops_edge_when_component_excluded(test_db, journey, pipeline, pipeline_2): |
| 174 | + JourneyDagEdge.create(journey=journey, left=pipeline, right=pipeline_2) |
| 175 | + journey.component_include_patterns = "*" |
| 176 | + journey.component_exclude_patterns = "P2" |
| 177 | + JourneyService.apply_component_patterns(journey) |
| 178 | + edges = list(JourneyDagEdge.select().where(JourneyDagEdge.journey == journey)) |
| 179 | + assert len(edges) == 1 |
| 180 | + assert edges[0].right_id == pipeline.id |
| 181 | + |
| 182 | + |
| 183 | +# --- add_component_to_matching_journeys --- |
| 184 | + |
| 185 | + |
| 186 | +@pytest.mark.integration |
| 187 | +def test_add_component_to_matching_journeys_matches(test_db, journey, project, pipeline): |
| 188 | + journey.component_include_patterns = "*" |
| 189 | + journey.save() |
| 190 | + JourneyService.add_component_to_matching_journeys(pipeline) |
| 191 | + edges = list(JourneyDagEdge.select().where(JourneyDagEdge.journey == journey)) |
| 192 | + assert len(edges) == 1 |
| 193 | + assert edges[0].left_id is None |
| 194 | + assert edges[0].right_id == pipeline.id |
| 195 | + |
| 196 | + |
| 197 | +@pytest.mark.integration |
| 198 | +def test_add_component_to_matching_journeys_no_include_skips(test_db, journey, pipeline): |
| 199 | + JourneyService.add_component_to_matching_journeys(pipeline) |
| 200 | + assert JourneyDagEdge.select().where(JourneyDagEdge.journey == journey).count() == 0 |
| 201 | + |
| 202 | + |
| 203 | +@pytest.mark.integration |
| 204 | +def test_add_component_to_matching_journeys_excluded(test_db, journey, pipeline): |
| 205 | + journey.component_include_patterns = "*" |
| 206 | + journey.component_exclude_patterns = "P1" |
| 207 | + journey.save() |
| 208 | + JourneyService.add_component_to_matching_journeys(pipeline) |
| 209 | + assert JourneyDagEdge.select().where(JourneyDagEdge.journey == journey).count() == 0 |
| 210 | + |
| 211 | + |
| 212 | +@pytest.mark.integration |
| 213 | +def test_add_component_to_matching_journeys_only_matching_journey(test_db, journey, journey_2, pipeline): |
| 214 | + journey.component_include_patterns = "P1" |
| 215 | + journey.save() |
| 216 | + journey_2.component_include_patterns = "other-*" |
| 217 | + journey_2.save() |
| 218 | + JourneyService.add_component_to_matching_journeys(pipeline) |
| 219 | + assert JourneyDagEdge.select().where(JourneyDagEdge.journey == journey).count() == 1 |
| 220 | + assert JourneyDagEdge.select().where(JourneyDagEdge.journey == journey_2).count() == 0 |
| 221 | + |
| 222 | + |
11 | 223 | @pytest.mark.integration |
12 | 224 | def test_get_rules_with_rules_journey_exists(test_db, journey, rule): |
13 | 225 | rules_page = JourneyService.get_rules_with_rules(journey.id, ListRules()) |
|
0 commit comments