BoilerWorks

boilerworks / tests / test_manifest.py
Blame History Raw 147 lines
1
"""Tests for boilerworks.manifest."""
2
3
from __future__ import annotations
4
5
import pytest
6
from pydantic import ValidationError
7
8
from boilerworks.manifest import BoilerworksManifest, DataConfig, ServicesConfig
9
from boilerworks.manifest import TestingConfig as TestingCfg
10
11
12
def _make_manifest(**kwargs) -> BoilerworksManifest:
13
defaults = {
14
"project": "my-app",
15
"family": "django-nextjs",
16
"size": "full",
17
}
18
defaults.update(kwargs)
19
return BoilerworksManifest(**defaults)
20
21
22
class TestValidManifest:
23
def test_minimal_manifest_passes(self) -> None:
24
m = _make_manifest()
25
assert m.project == "my-app"
26
assert m.family == "django-nextjs"
27
assert m.size == "full"
28
29
def test_defaults_are_correct(self) -> None:
30
m = _make_manifest()
31
assert m.topology == "standard"
32
assert m.cloud is None
33
assert m.region is None
34
assert m.domain is None
35
assert m.mobile is False
36
assert m.web_presence is False
37
assert m.compliance == []
38
assert m.template_versions == {}
39
40
def test_full_manifest_passes(self, valid_manifest: BoilerworksManifest) -> None:
41
assert valid_manifest.project == "my-app"
42
assert valid_manifest.cloud == "aws"
43
assert valid_manifest.region == "us-east-1"
44
45
def test_micro_template(self) -> None:
46
m = _make_manifest(family="fastapi-micro", size="micro")
47
assert m.size == "micro"
48
49
def test_edge_template(self) -> None:
50
m = _make_manifest(family="astro-site", size="edge")
51
assert m.size == "edge"
52
53
54
class TestProjectSlugValidation:
55
def test_valid_slugs(self) -> None:
56
for slug in ["my-app", "app", "my-app-v2", "a1b2c3"]:
57
m = _make_manifest(project=slug)
58
assert m.project == slug
59
60
def test_spaces_fail(self) -> None:
61
with pytest.raises(ValidationError, match="project name"):
62
_make_manifest(project="my app")
63
64
def test_uppercase_fails(self) -> None:
65
with pytest.raises(ValidationError, match="project name"):
66
_make_manifest(project="MyApp")
67
68
def test_leading_digit_fails(self) -> None:
69
with pytest.raises(ValidationError, match="project name"):
70
_make_manifest(project="1app")
71
72
def test_underscore_fails(self) -> None:
73
with pytest.raises(ValidationError, match="project name"):
74
_make_manifest(project="my_app")
75
76
def test_empty_fails(self) -> None:
77
with pytest.raises(ValidationError):
78
_make_manifest(project="")
79
80
81
class TestFamilyValidation:
82
def test_unknown_family_fails(self) -> None:
83
with pytest.raises(ValidationError, match="unknown template family"):
84
_make_manifest(family="not-a-real-template")
85
86
def test_all_known_families_pass(self) -> None:
87
from boilerworks.registry import Registry
88
89
registry = Registry()
90
for t in registry.list_all():
91
m = _make_manifest(family=t.name, size=t.size)
92
assert m.family == t.name
93
94
95
class TestYamlRoundtrip:
96
def test_to_yaml_and_back(self, valid_manifest: BoilerworksManifest) -> None:
97
yaml_str = valid_manifest.to_yaml()
98
assert "my-app" in yaml_str
99
assert "django-nextjs" in yaml_str
100
101
restored = BoilerworksManifest.from_yaml(yaml_str)
102
assert restored.project == valid_manifest.project
103
assert restored.family == valid_manifest.family
104
assert restored.size == valid_manifest.size
105
assert restored.cloud == valid_manifest.cloud
106
assert restored.region == valid_manifest.region
107
108
def test_to_yaml_is_valid_yaml(self, valid_manifest: BoilerworksManifest) -> None:
109
import yaml
110
111
yaml_str = valid_manifest.to_yaml()
112
parsed = yaml.safe_load(yaml_str)
113
assert isinstance(parsed, dict)
114
assert parsed["project"] == "my-app"
115
116
def test_from_file(self, valid_manifest: BoilerworksManifest, tmp_path) -> None:
117
yaml_file = tmp_path / "boilerworks.yaml"
118
valid_manifest.to_file(yaml_file)
119
120
loaded = BoilerworksManifest.from_file(yaml_file)
121
assert loaded.project == valid_manifest.project
122
assert loaded.family == valid_manifest.family
123
124
125
class TestNestedModels:
126
def test_services_config_defaults(self) -> None:
127
s = ServicesConfig()
128
assert s.email is None
129
assert s.cache == "redis"
130
131
def test_data_config_defaults(self) -> None:
132
d = DataConfig()
133
assert d.database == "postgres"
134
assert d.migrations is True
135
assert d.seed_data is True
136
137
def test_testing_config_defaults(self) -> None:
138
t = TestingCfg()
139
assert t.e2e is None
140
assert t.unit is True
141
assert t.integration is True
142
143
def test_services_email_options(self) -> None:
144
for provider in ("ses", "sendgrid", "mailgun"):
145
s = ServicesConfig(email=provider)
146
assert s.email == provider
147

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button