julee 0.1.5__py3-none-any.whl → 0.1.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- julee/docs/sphinx_hcd/__init__.py +146 -13
- julee/docs/sphinx_hcd/domain/__init__.py +5 -0
- julee/docs/sphinx_hcd/domain/models/__init__.py +32 -0
- julee/docs/sphinx_hcd/domain/models/accelerator.py +152 -0
- julee/docs/sphinx_hcd/domain/models/app.py +151 -0
- julee/docs/sphinx_hcd/domain/models/code_info.py +121 -0
- julee/docs/sphinx_hcd/domain/models/epic.py +79 -0
- julee/docs/sphinx_hcd/domain/models/integration.py +230 -0
- julee/docs/sphinx_hcd/domain/models/journey.py +222 -0
- julee/docs/sphinx_hcd/domain/models/persona.py +106 -0
- julee/docs/sphinx_hcd/domain/models/story.py +128 -0
- julee/docs/sphinx_hcd/domain/repositories/__init__.py +25 -0
- julee/docs/sphinx_hcd/domain/repositories/accelerator.py +98 -0
- julee/docs/sphinx_hcd/domain/repositories/app.py +57 -0
- julee/docs/sphinx_hcd/domain/repositories/base.py +89 -0
- julee/docs/sphinx_hcd/domain/repositories/code_info.py +69 -0
- julee/docs/sphinx_hcd/domain/repositories/epic.py +62 -0
- julee/docs/sphinx_hcd/domain/repositories/integration.py +79 -0
- julee/docs/sphinx_hcd/domain/repositories/journey.py +106 -0
- julee/docs/sphinx_hcd/domain/repositories/story.py +68 -0
- julee/docs/sphinx_hcd/domain/use_cases/__init__.py +64 -0
- julee/docs/sphinx_hcd/domain/use_cases/derive_personas.py +166 -0
- julee/docs/sphinx_hcd/domain/use_cases/resolve_accelerator_references.py +236 -0
- julee/docs/sphinx_hcd/domain/use_cases/resolve_app_references.py +144 -0
- julee/docs/sphinx_hcd/domain/use_cases/resolve_story_references.py +121 -0
- julee/docs/sphinx_hcd/parsers/__init__.py +48 -0
- julee/docs/sphinx_hcd/parsers/ast.py +150 -0
- julee/docs/sphinx_hcd/parsers/gherkin.py +155 -0
- julee/docs/sphinx_hcd/parsers/yaml.py +184 -0
- julee/docs/sphinx_hcd/repositories/__init__.py +4 -0
- julee/docs/sphinx_hcd/repositories/memory/__init__.py +25 -0
- julee/docs/sphinx_hcd/repositories/memory/accelerator.py +86 -0
- julee/docs/sphinx_hcd/repositories/memory/app.py +45 -0
- julee/docs/sphinx_hcd/repositories/memory/base.py +106 -0
- julee/docs/sphinx_hcd/repositories/memory/code_info.py +59 -0
- julee/docs/sphinx_hcd/repositories/memory/epic.py +54 -0
- julee/docs/sphinx_hcd/repositories/memory/integration.py +70 -0
- julee/docs/sphinx_hcd/repositories/memory/journey.py +96 -0
- julee/docs/sphinx_hcd/repositories/memory/story.py +63 -0
- julee/docs/sphinx_hcd/sphinx/__init__.py +28 -0
- julee/docs/sphinx_hcd/sphinx/adapters.py +116 -0
- julee/docs/sphinx_hcd/sphinx/context.py +163 -0
- julee/docs/sphinx_hcd/sphinx/directives/__init__.py +160 -0
- julee/docs/sphinx_hcd/sphinx/directives/accelerator.py +576 -0
- julee/docs/sphinx_hcd/sphinx/directives/app.py +349 -0
- julee/docs/sphinx_hcd/sphinx/directives/base.py +211 -0
- julee/docs/sphinx_hcd/sphinx/directives/epic.py +434 -0
- julee/docs/sphinx_hcd/sphinx/directives/integration.py +220 -0
- julee/docs/sphinx_hcd/sphinx/directives/journey.py +642 -0
- julee/docs/sphinx_hcd/sphinx/directives/persona.py +345 -0
- julee/docs/sphinx_hcd/sphinx/directives/story.py +575 -0
- julee/docs/sphinx_hcd/sphinx/event_handlers/__init__.py +16 -0
- julee/docs/sphinx_hcd/sphinx/event_handlers/builder_inited.py +31 -0
- julee/docs/sphinx_hcd/sphinx/event_handlers/doctree_read.py +27 -0
- julee/docs/sphinx_hcd/sphinx/event_handlers/doctree_resolved.py +43 -0
- julee/docs/sphinx_hcd/sphinx/event_handlers/env_purge_doc.py +42 -0
- julee/docs/sphinx_hcd/sphinx/initialization.py +139 -0
- julee/docs/sphinx_hcd/tests/__init__.py +9 -0
- julee/docs/sphinx_hcd/tests/conftest.py +6 -0
- julee/docs/sphinx_hcd/tests/domain/__init__.py +1 -0
- julee/docs/sphinx_hcd/tests/domain/models/__init__.py +1 -0
- julee/docs/sphinx_hcd/tests/domain/models/test_accelerator.py +266 -0
- julee/docs/sphinx_hcd/tests/domain/models/test_app.py +258 -0
- julee/docs/sphinx_hcd/tests/domain/models/test_code_info.py +231 -0
- julee/docs/sphinx_hcd/tests/domain/models/test_epic.py +163 -0
- julee/docs/sphinx_hcd/tests/domain/models/test_integration.py +327 -0
- julee/docs/sphinx_hcd/tests/domain/models/test_journey.py +249 -0
- julee/docs/sphinx_hcd/tests/domain/models/test_persona.py +172 -0
- julee/docs/sphinx_hcd/tests/domain/models/test_story.py +216 -0
- julee/docs/sphinx_hcd/tests/domain/use_cases/__init__.py +1 -0
- julee/docs/sphinx_hcd/tests/domain/use_cases/test_derive_personas.py +314 -0
- julee/docs/sphinx_hcd/tests/domain/use_cases/test_resolve_accelerator_references.py +476 -0
- julee/docs/sphinx_hcd/tests/domain/use_cases/test_resolve_app_references.py +265 -0
- julee/docs/sphinx_hcd/tests/domain/use_cases/test_resolve_story_references.py +229 -0
- julee/docs/sphinx_hcd/tests/integration/__init__.py +1 -0
- julee/docs/sphinx_hcd/tests/parsers/__init__.py +1 -0
- julee/docs/sphinx_hcd/tests/parsers/test_ast.py +298 -0
- julee/docs/sphinx_hcd/tests/parsers/test_gherkin.py +282 -0
- julee/docs/sphinx_hcd/tests/parsers/test_yaml.py +496 -0
- julee/docs/sphinx_hcd/tests/repositories/__init__.py +1 -0
- julee/docs/sphinx_hcd/tests/repositories/test_accelerator.py +298 -0
- julee/docs/sphinx_hcd/tests/repositories/test_app.py +218 -0
- julee/docs/sphinx_hcd/tests/repositories/test_base.py +151 -0
- julee/docs/sphinx_hcd/tests/repositories/test_code_info.py +253 -0
- julee/docs/sphinx_hcd/tests/repositories/test_epic.py +237 -0
- julee/docs/sphinx_hcd/tests/repositories/test_integration.py +268 -0
- julee/docs/sphinx_hcd/tests/repositories/test_journey.py +294 -0
- julee/docs/sphinx_hcd/tests/repositories/test_story.py +236 -0
- julee/docs/sphinx_hcd/tests/sphinx/__init__.py +1 -0
- julee/docs/sphinx_hcd/tests/sphinx/directives/__init__.py +1 -0
- julee/docs/sphinx_hcd/tests/sphinx/directives/test_base.py +160 -0
- julee/docs/sphinx_hcd/tests/sphinx/test_adapters.py +176 -0
- julee/docs/sphinx_hcd/tests/sphinx/test_context.py +257 -0
- {julee-0.1.5.dist-info → julee-0.1.6.dist-info}/METADATA +2 -1
- {julee-0.1.5.dist-info → julee-0.1.6.dist-info}/RECORD +98 -13
- julee/docs/sphinx_hcd/accelerators.py +0 -1175
- julee/docs/sphinx_hcd/apps.py +0 -518
- julee/docs/sphinx_hcd/epics.py +0 -453
- julee/docs/sphinx_hcd/integrations.py +0 -310
- julee/docs/sphinx_hcd/journeys.py +0 -797
- julee/docs/sphinx_hcd/personas.py +0 -457
- julee/docs/sphinx_hcd/stories.py +0 -960
- {julee-0.1.5.dist-info → julee-0.1.6.dist-info}/WHEEL +0 -0
- {julee-0.1.5.dist-info → julee-0.1.6.dist-info}/licenses/LICENSE +0 -0
- {julee-0.1.5.dist-info → julee-0.1.6.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
"""Tests for derive_personas use case."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from julee.docs.sphinx_hcd.domain.models.app import App, AppType
|
|
6
|
+
from julee.docs.sphinx_hcd.domain.models.epic import Epic
|
|
7
|
+
from julee.docs.sphinx_hcd.domain.models.story import Story
|
|
8
|
+
from julee.docs.sphinx_hcd.domain.use_cases.derive_personas import (
|
|
9
|
+
derive_personas,
|
|
10
|
+
derive_personas_by_app_type,
|
|
11
|
+
get_apps_for_persona,
|
|
12
|
+
get_epics_for_persona,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def create_story(
|
|
17
|
+
feature_title: str,
|
|
18
|
+
persona: str,
|
|
19
|
+
app_slug: str,
|
|
20
|
+
) -> Story:
|
|
21
|
+
"""Helper to create test stories."""
|
|
22
|
+
return Story(
|
|
23
|
+
slug=feature_title.lower().replace(" ", "-"),
|
|
24
|
+
feature_title=feature_title,
|
|
25
|
+
persona=persona,
|
|
26
|
+
i_want="test want",
|
|
27
|
+
so_that="test outcome",
|
|
28
|
+
app_slug=app_slug,
|
|
29
|
+
file_path=f"features/{app_slug}.feature",
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def create_epic(
|
|
34
|
+
slug: str,
|
|
35
|
+
story_refs: list[str],
|
|
36
|
+
) -> Epic:
|
|
37
|
+
"""Helper to create test epics."""
|
|
38
|
+
return Epic(
|
|
39
|
+
slug=slug,
|
|
40
|
+
description=f"Epic for {slug}",
|
|
41
|
+
story_refs=story_refs,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def create_app(
|
|
46
|
+
slug: str,
|
|
47
|
+
name: str,
|
|
48
|
+
app_type: AppType = AppType.STAFF,
|
|
49
|
+
) -> App:
|
|
50
|
+
"""Helper to create test apps."""
|
|
51
|
+
return App(
|
|
52
|
+
slug=slug,
|
|
53
|
+
name=name,
|
|
54
|
+
app_type=app_type,
|
|
55
|
+
manifest_path=f"apps/{slug}/app.yaml",
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class TestDerivePersonas:
|
|
60
|
+
"""Test derive_personas function."""
|
|
61
|
+
|
|
62
|
+
def test_derive_single_persona(self) -> None:
|
|
63
|
+
"""Test deriving a single persona from stories."""
|
|
64
|
+
stories = [
|
|
65
|
+
create_story("Upload Document", "Knowledge Curator", "vocabulary-tool"),
|
|
66
|
+
create_story("Review Vocabulary", "Knowledge Curator", "vocabulary-tool"),
|
|
67
|
+
]
|
|
68
|
+
epics: list[Epic] = []
|
|
69
|
+
|
|
70
|
+
personas = derive_personas(stories, epics)
|
|
71
|
+
|
|
72
|
+
assert len(personas) == 1
|
|
73
|
+
assert personas[0].name == "Knowledge Curator"
|
|
74
|
+
assert personas[0].app_slugs == ["vocabulary-tool"]
|
|
75
|
+
|
|
76
|
+
def test_derive_multiple_personas(self) -> None:
|
|
77
|
+
"""Test deriving multiple personas from stories."""
|
|
78
|
+
stories = [
|
|
79
|
+
create_story("Upload Document", "Knowledge Curator", "vocabulary-tool"),
|
|
80
|
+
create_story("Run Analysis", "Analyst", "analytics-app"),
|
|
81
|
+
create_story("Configure System", "Administrator", "admin-portal"),
|
|
82
|
+
]
|
|
83
|
+
epics: list[Epic] = []
|
|
84
|
+
|
|
85
|
+
personas = derive_personas(stories, epics)
|
|
86
|
+
|
|
87
|
+
assert len(personas) == 3
|
|
88
|
+
names = [p.name for p in personas]
|
|
89
|
+
assert "Administrator" in names
|
|
90
|
+
assert "Analyst" in names
|
|
91
|
+
assert "Knowledge Curator" in names
|
|
92
|
+
|
|
93
|
+
def test_derive_persona_with_multiple_apps(self) -> None:
|
|
94
|
+
"""Test persona using multiple apps."""
|
|
95
|
+
stories = [
|
|
96
|
+
create_story("Upload Document", "Knowledge Curator", "vocabulary-tool"),
|
|
97
|
+
create_story("Manage Users", "Knowledge Curator", "admin-portal"),
|
|
98
|
+
create_story("Review Data", "Knowledge Curator", "analytics-app"),
|
|
99
|
+
]
|
|
100
|
+
epics: list[Epic] = []
|
|
101
|
+
|
|
102
|
+
personas = derive_personas(stories, epics)
|
|
103
|
+
|
|
104
|
+
assert len(personas) == 1
|
|
105
|
+
persona = personas[0]
|
|
106
|
+
assert set(persona.app_slugs) == {
|
|
107
|
+
"vocabulary-tool",
|
|
108
|
+
"admin-portal",
|
|
109
|
+
"analytics-app",
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
def test_derive_persona_with_epics(self) -> None:
|
|
113
|
+
"""Test persona epic association."""
|
|
114
|
+
stories = [
|
|
115
|
+
create_story("Upload Document", "Knowledge Curator", "vocabulary-tool"),
|
|
116
|
+
create_story("Review Vocabulary", "Knowledge Curator", "vocabulary-tool"),
|
|
117
|
+
]
|
|
118
|
+
epics = [
|
|
119
|
+
create_epic(
|
|
120
|
+
"vocabulary-management", ["Upload Document", "Review Vocabulary"]
|
|
121
|
+
),
|
|
122
|
+
create_epic(
|
|
123
|
+
"credential-creation", ["Create Credential"]
|
|
124
|
+
), # Different persona
|
|
125
|
+
]
|
|
126
|
+
|
|
127
|
+
personas = derive_personas(stories, epics)
|
|
128
|
+
|
|
129
|
+
assert len(personas) == 1
|
|
130
|
+
persona = personas[0]
|
|
131
|
+
assert persona.epic_slugs == ["vocabulary-management"]
|
|
132
|
+
|
|
133
|
+
def test_derive_skips_unknown_persona(self) -> None:
|
|
134
|
+
"""Test that 'unknown' persona is skipped."""
|
|
135
|
+
stories = [
|
|
136
|
+
create_story("Upload Document", "Knowledge Curator", "vocabulary-tool"),
|
|
137
|
+
create_story("Unknown Feature", "unknown", "some-app"),
|
|
138
|
+
]
|
|
139
|
+
epics: list[Epic] = []
|
|
140
|
+
|
|
141
|
+
personas = derive_personas(stories, epics)
|
|
142
|
+
|
|
143
|
+
assert len(personas) == 1
|
|
144
|
+
assert personas[0].name == "Knowledge Curator"
|
|
145
|
+
|
|
146
|
+
def test_derive_empty_lists(self) -> None:
|
|
147
|
+
"""Test with empty input lists."""
|
|
148
|
+
personas = derive_personas([], [])
|
|
149
|
+
assert personas == []
|
|
150
|
+
|
|
151
|
+
def test_derive_sorted_by_name(self) -> None:
|
|
152
|
+
"""Test personas are sorted by name."""
|
|
153
|
+
stories = [
|
|
154
|
+
create_story("Feature Z", "Zebra User", "app-z"),
|
|
155
|
+
create_story("Feature A", "Alpha User", "app-a"),
|
|
156
|
+
create_story("Feature M", "Middle User", "app-m"),
|
|
157
|
+
]
|
|
158
|
+
epics: list[Epic] = []
|
|
159
|
+
|
|
160
|
+
personas = derive_personas(stories, epics)
|
|
161
|
+
|
|
162
|
+
names = [p.name for p in personas]
|
|
163
|
+
assert names == ["Alpha User", "Middle User", "Zebra User"]
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class TestDerivePersonasByAppType:
|
|
167
|
+
"""Test derive_personas_by_app_type function."""
|
|
168
|
+
|
|
169
|
+
def test_group_by_app_type(self) -> None:
|
|
170
|
+
"""Test grouping personas by app type."""
|
|
171
|
+
stories = [
|
|
172
|
+
create_story("Upload Document", "Knowledge Curator", "vocabulary-tool"),
|
|
173
|
+
create_story("View Portal", "Customer", "customer-portal"),
|
|
174
|
+
]
|
|
175
|
+
epics: list[Epic] = []
|
|
176
|
+
apps = [
|
|
177
|
+
create_app("vocabulary-tool", "Vocabulary Tool", AppType.STAFF),
|
|
178
|
+
create_app("customer-portal", "Customer Portal", AppType.EXTERNAL),
|
|
179
|
+
]
|
|
180
|
+
|
|
181
|
+
personas_by_type = derive_personas_by_app_type(stories, epics, apps)
|
|
182
|
+
|
|
183
|
+
assert "staff" in personas_by_type
|
|
184
|
+
assert "external" in personas_by_type
|
|
185
|
+
assert len(personas_by_type["staff"]) == 1
|
|
186
|
+
assert personas_by_type["staff"][0].name == "Knowledge Curator"
|
|
187
|
+
assert len(personas_by_type["external"]) == 1
|
|
188
|
+
assert personas_by_type["external"][0].name == "Customer"
|
|
189
|
+
|
|
190
|
+
def test_persona_in_multiple_types(self) -> None:
|
|
191
|
+
"""Test persona using apps of different types."""
|
|
192
|
+
stories = [
|
|
193
|
+
create_story("Upload Document", "Power User", "staff-tool"),
|
|
194
|
+
create_story("View Portal", "Power User", "external-portal"),
|
|
195
|
+
]
|
|
196
|
+
epics: list[Epic] = []
|
|
197
|
+
apps = [
|
|
198
|
+
create_app("staff-tool", "Staff Tool", AppType.STAFF),
|
|
199
|
+
create_app("external-portal", "External Portal", AppType.EXTERNAL),
|
|
200
|
+
]
|
|
201
|
+
|
|
202
|
+
personas_by_type = derive_personas_by_app_type(stories, epics, apps)
|
|
203
|
+
|
|
204
|
+
# Power User appears in both groups
|
|
205
|
+
assert any(p.name == "Power User" for p in personas_by_type.get("staff", []))
|
|
206
|
+
assert any(p.name == "Power User" for p in personas_by_type.get("external", []))
|
|
207
|
+
|
|
208
|
+
def test_unknown_app_type(self) -> None:
|
|
209
|
+
"""Test handling of unknown app type."""
|
|
210
|
+
stories = [
|
|
211
|
+
create_story("Upload Document", "User", "unknown-app"),
|
|
212
|
+
]
|
|
213
|
+
epics: list[Epic] = []
|
|
214
|
+
apps: list[App] = [] # No app definitions
|
|
215
|
+
|
|
216
|
+
personas_by_type = derive_personas_by_app_type(stories, epics, apps)
|
|
217
|
+
|
|
218
|
+
assert "unknown" in personas_by_type
|
|
219
|
+
assert len(personas_by_type["unknown"]) == 1
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class TestGetEpicsForPersona:
|
|
223
|
+
"""Test get_epics_for_persona function."""
|
|
224
|
+
|
|
225
|
+
@pytest.fixture
|
|
226
|
+
def sample_data(self) -> tuple[list[Story], list[Epic]]:
|
|
227
|
+
"""Create sample test data."""
|
|
228
|
+
stories = [
|
|
229
|
+
create_story("Upload Document", "Knowledge Curator", "vocabulary-tool"),
|
|
230
|
+
create_story("Review Vocabulary", "Knowledge Curator", "vocabulary-tool"),
|
|
231
|
+
create_story("Run Analysis", "Analyst", "analytics-app"),
|
|
232
|
+
]
|
|
233
|
+
epics = [
|
|
234
|
+
create_epic(
|
|
235
|
+
"vocabulary-management", ["Upload Document", "Review Vocabulary"]
|
|
236
|
+
),
|
|
237
|
+
create_epic("analytics", ["Run Analysis"]),
|
|
238
|
+
create_epic("mixed-epic", ["Upload Document", "Run Analysis"]),
|
|
239
|
+
]
|
|
240
|
+
return stories, epics
|
|
241
|
+
|
|
242
|
+
def test_get_epics_for_persona(
|
|
243
|
+
self, sample_data: tuple[list[Story], list[Epic]]
|
|
244
|
+
) -> None:
|
|
245
|
+
"""Test getting epics for a persona."""
|
|
246
|
+
stories, epics = sample_data
|
|
247
|
+
all_personas = derive_personas(stories, epics)
|
|
248
|
+
curator = next(p for p in all_personas if p.name == "Knowledge Curator")
|
|
249
|
+
|
|
250
|
+
persona_epics = get_epics_for_persona(curator, epics, stories)
|
|
251
|
+
|
|
252
|
+
assert len(persona_epics) == 2
|
|
253
|
+
slugs = {e.slug for e in persona_epics}
|
|
254
|
+
assert slugs == {"vocabulary-management", "mixed-epic"}
|
|
255
|
+
|
|
256
|
+
def test_get_epics_sorted_by_slug(
|
|
257
|
+
self, sample_data: tuple[list[Story], list[Epic]]
|
|
258
|
+
) -> None:
|
|
259
|
+
"""Test epics are sorted by slug."""
|
|
260
|
+
stories, epics = sample_data
|
|
261
|
+
all_personas = derive_personas(stories, epics)
|
|
262
|
+
curator = next(p for p in all_personas if p.name == "Knowledge Curator")
|
|
263
|
+
|
|
264
|
+
persona_epics = get_epics_for_persona(curator, epics, stories)
|
|
265
|
+
|
|
266
|
+
slugs = [e.slug for e in persona_epics]
|
|
267
|
+
assert slugs == sorted(slugs)
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
class TestGetAppsForPersona:
|
|
271
|
+
"""Test get_apps_for_persona function."""
|
|
272
|
+
|
|
273
|
+
def test_get_apps_for_persona(self) -> None:
|
|
274
|
+
"""Test getting apps for a persona."""
|
|
275
|
+
stories = [
|
|
276
|
+
create_story("Upload Document", "Knowledge Curator", "vocabulary-tool"),
|
|
277
|
+
create_story("Admin Task", "Knowledge Curator", "admin-portal"),
|
|
278
|
+
]
|
|
279
|
+
epics: list[Epic] = []
|
|
280
|
+
apps = [
|
|
281
|
+
create_app("vocabulary-tool", "Vocabulary Tool"),
|
|
282
|
+
create_app("admin-portal", "Admin Portal"),
|
|
283
|
+
create_app("other-app", "Other App"), # Not used by this persona
|
|
284
|
+
]
|
|
285
|
+
|
|
286
|
+
all_personas = derive_personas(stories, epics)
|
|
287
|
+
curator = all_personas[0]
|
|
288
|
+
|
|
289
|
+
persona_apps = get_apps_for_persona(curator, apps)
|
|
290
|
+
|
|
291
|
+
assert len(persona_apps) == 2
|
|
292
|
+
slugs = {a.slug for a in persona_apps}
|
|
293
|
+
assert slugs == {"vocabulary-tool", "admin-portal"}
|
|
294
|
+
|
|
295
|
+
def test_get_apps_missing_app_definition(self) -> None:
|
|
296
|
+
"""Test handling when app definition is missing."""
|
|
297
|
+
stories = [
|
|
298
|
+
create_story("Upload Document", "User", "defined-app"),
|
|
299
|
+
create_story("Other Task", "User", "undefined-app"),
|
|
300
|
+
]
|
|
301
|
+
epics: list[Epic] = []
|
|
302
|
+
apps = [
|
|
303
|
+
create_app("defined-app", "Defined App"),
|
|
304
|
+
# undefined-app is not in the list
|
|
305
|
+
]
|
|
306
|
+
|
|
307
|
+
all_personas = derive_personas(stories, epics)
|
|
308
|
+
user = all_personas[0]
|
|
309
|
+
|
|
310
|
+
persona_apps = get_apps_for_persona(user, apps)
|
|
311
|
+
|
|
312
|
+
# Only the defined app is returned
|
|
313
|
+
assert len(persona_apps) == 1
|
|
314
|
+
assert persona_apps[0].slug == "defined-app"
|