Repository navigation
Expand file tree
/
Copy pathtest_rules.py
More file actions
160 lines (111 loc) · 5.07 KB
/
Copy pathtest_rules.py
File metadata and controls
160 lines (111 loc) · 5.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import dataclasses
import pytest
from becwright.rules import RULES_SCHEMA_VERSION, Rule, RulesError, load_rules
def _write(tmp_path, text):
path = tmp_path / "rules.yaml"
path.write_text(text, encoding="utf-8")
return path
# The `.bec/rules.yaml` field set is frozen as of schema_version 1: from 1.0.0 on,
# a field is only added/removed under the deprecation policy (README). This test
# makes a change to the set a deliberate, reviewed break rather than an accident.
_FROZEN_RULE_FIELDS = {
"id", "paths", "check", "exclude", "intent",
"why_it_matters", "rejected_alternatives", "severity", "target",
}
def test_rule_field_set_is_frozen():
assert {f.name for f in dataclasses.fields(Rule)} == _FROZEN_RULE_FIELDS
def test_missing_file_returns_empty(tmp_path):
assert load_rules(tmp_path / "nope.yaml") == []
def test_loads_valid_rules(tmp_path):
path = _write(tmp_path, 'rules:\n - id: r1\n check: "true"\n severity: warning\n')
rules = load_rules(path)
assert len(rules) == 1 and rules[0].is_blocking is False
def test_invalid_severity_raises(tmp_path):
path = _write(tmp_path, 'rules:\n - id: r1\n check: "true"\n severity: blockign\n')
with pytest.raises(RulesError, match="invalid severity"):
load_rules(path)
def test_invalid_yaml_raises_friendly_error(tmp_path):
path = _write(tmp_path, "rules:\n - id: r1\n check: bad-indent\n")
with pytest.raises(RulesError, match="invalid YAML"):
load_rules(path)
def test_missing_required_field_raises(tmp_path):
path = _write(tmp_path, "rules:\n - id: r1\n")
with pytest.raises(RulesError, match="'check'"):
load_rules(path)
def test_non_list_rules_raises(tmp_path):
path = _write(tmp_path, "rules: not-a-list\n")
with pytest.raises(RulesError, match="'rules:' list"):
load_rules(path)
def test_loads_exclude(tmp_path):
path = _write(
tmp_path,
'rules:\n - id: r1\n check: "true"\n paths: ["**/*.py"]\n'
' exclude: ["lib/logger.py"]\n',
)
assert load_rules(path)[0].exclude == ("lib/logger.py",)
def test_exclude_defaults_empty(tmp_path):
path = _write(tmp_path, 'rules:\n - id: r1\n check: "true"\n')
assert load_rules(path)[0].exclude == ()
def test_loads_commit_msg_target(tmp_path):
path = _write(tmp_path, 'rules:\n - id: r1\n check: "true"\n target: commit-msg\n')
assert load_rules(path)[0].target == "commit-msg"
def test_target_defaults_to_files(tmp_path):
path = _write(tmp_path, 'rules:\n - id: r1\n check: "true"\n')
assert load_rules(path)[0].target == "files"
def test_invalid_target_raises(tmp_path):
path = _write(tmp_path, 'rules:\n - id: r1\n check: "true"\n target: mensaje\n')
with pytest.raises(RulesError, match="invalid target"):
load_rules(path)
def test_loads_advisory_severity(tmp_path):
path = _write(tmp_path, 'rules:\n - id: r1\n check: "true"\n severity: advisory\n')
rule = load_rules(path)[0]
assert rule.is_advisory is True and rule.is_blocking is False
def test_absent_schema_version_loads(tmp_path):
path = _write(tmp_path, 'rules:\n - id: r1\n check: "true"\n')
assert len(load_rules(path)) == 1
def test_current_schema_version_loads(tmp_path):
path = _write(
tmp_path,
f'schema_version: {RULES_SCHEMA_VERSION}\nrules:\n - id: r1\n check: "true"\n',
)
assert len(load_rules(path)) == 1
def test_newer_schema_version_raises(tmp_path):
path = _write(
tmp_path,
f'schema_version: {RULES_SCHEMA_VERSION + 1}\nrules:\n - id: r1\n check: "true"\n',
)
with pytest.raises(RulesError, match="newer"):
load_rules(path)
def test_non_integer_schema_version_raises(tmp_path):
path = _write(tmp_path, 'schema_version: one\nrules:\n - id: r1\n check: "true"\n')
with pytest.raises(RulesError, match="schema_version"):
load_rules(path)
def test_non_positive_schema_version_raises(tmp_path):
path = _write(tmp_path, 'schema_version: 0\nrules:\n - id: r1\n check: "true"\n')
with pytest.raises(RulesError, match="schema_version"):
load_rules(path)
def test_global_exclude_merges_with_rule_exclude(tmp_path):
path = _write(
tmp_path,
'global_exclude:\n - "vendor/**"\n - "build/**"\n'
'rules:\n - id: r1\n check: "true"\n exclude: ["local/exclude.py"]\n'
)
rules = load_rules(path)
assert len(rules) == 1
assert rules[0].exclude == ("local/exclude.py", "vendor/**", "build/**")
def test_global_exclude_not_list_raises(tmp_path):
path = _write(
tmp_path,
'global_exclude: "not-a-list"\n'
'rules:\n - id: r1\n check: "true"\n'
)
with pytest.raises(RulesError, match="global_exclude must be a list"):
load_rules(path)
def test_global_exclude_non_string_elements_raises(tmp_path):
path = _write(
tmp_path,
'global_exclude:\n - 123\n'
'rules:\n - id: r1\n check: "true"\n'
)
with pytest.raises(RulesError, match="global_exclude must be a list"):
load_rules(path)