ga4-cli 0.1.0__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.
- ga4_cli-0.1.0.dist-info/METADATA +253 -0
- ga4_cli-0.1.0.dist-info/RECORD +32 -0
- ga4_cli-0.1.0.dist-info/WHEEL +5 -0
- ga4_cli-0.1.0.dist-info/entry_points.txt +2 -0
- ga4_cli-0.1.0.dist-info/licenses/LICENSE +21 -0
- ga4_cli-0.1.0.dist-info/top_level.txt +2 -0
- ga_cli/__init__.py +3 -0
- ga_cli/auth.py +59 -0
- ga_cli/cli.py +35 -0
- ga_cli/commands/__init__.py +0 -0
- ga_cli/commands/accounts.py +81 -0
- ga_cli/commands/config.py +65 -0
- ga_cli/commands/datastreams.py +146 -0
- ga_cli/commands/properties.py +151 -0
- ga_cli/config.py +95 -0
- ga_cli/decorators.py +90 -0
- ga_cli/errors.py +35 -0
- ga_cli/formatters/__init__.py +0 -0
- ga_cli/formatters/json.py +9 -0
- ga_cli/formatters/table.py +23 -0
- ga_cli/logging_config.py +44 -0
- ga_cli/output.py +59 -0
- ga_cli/retry.py +40 -0
- ga_cli/validators.py +52 -0
- tests/__init__.py +0 -0
- tests/conftest.py +89 -0
- tests/test_accounts.py +49 -0
- tests/test_auth.py +74 -0
- tests/test_cli.py +52 -0
- tests/test_config.py +140 -0
- tests/test_errors.py +73 -0
- tests/test_validators.py +146 -0
tests/test_validators.py
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"""Tests for input validators"""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
import click
|
|
5
|
+
from ga_cli.validators import (
|
|
6
|
+
validate_account_id,
|
|
7
|
+
validate_property_id,
|
|
8
|
+
validate_url,
|
|
9
|
+
validate_timezone,
|
|
10
|
+
validate_currency,
|
|
11
|
+
validate_stream_id,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class TestValidateAccountId:
|
|
16
|
+
"""Test account ID validation"""
|
|
17
|
+
|
|
18
|
+
def test_valid_account_id(self):
|
|
19
|
+
"""Test validation with valid account ID"""
|
|
20
|
+
result = validate_account_id(None, None, "123456")
|
|
21
|
+
assert result == "123456"
|
|
22
|
+
|
|
23
|
+
def test_invalid_account_id_non_numeric(self):
|
|
24
|
+
"""Test validation rejects non-numeric account ID"""
|
|
25
|
+
with pytest.raises(click.BadParameter, match="Account ID must be numeric"):
|
|
26
|
+
validate_account_id(None, None, "abc123")
|
|
27
|
+
|
|
28
|
+
def test_empty_account_id(self):
|
|
29
|
+
"""Test validation with empty value"""
|
|
30
|
+
result = validate_account_id(None, None, None)
|
|
31
|
+
assert result is None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class TestValidatePropertyId:
|
|
35
|
+
"""Test property ID validation"""
|
|
36
|
+
|
|
37
|
+
def test_valid_property_id(self):
|
|
38
|
+
"""Test validation with valid property ID"""
|
|
39
|
+
result = validate_property_id(None, None, "987654")
|
|
40
|
+
assert result == "987654"
|
|
41
|
+
|
|
42
|
+
def test_invalid_property_id_non_numeric(self):
|
|
43
|
+
"""Test validation rejects non-numeric property ID"""
|
|
44
|
+
with pytest.raises(click.BadParameter, match="Property ID must be numeric"):
|
|
45
|
+
validate_property_id(None, None, "prop-123")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class TestValidateUrl:
|
|
49
|
+
"""Test URL validation"""
|
|
50
|
+
|
|
51
|
+
def test_valid_https_url(self):
|
|
52
|
+
"""Test validation with valid HTTPS URL"""
|
|
53
|
+
result = validate_url(None, None, "https://example.com")
|
|
54
|
+
assert result == "https://example.com"
|
|
55
|
+
|
|
56
|
+
def test_valid_http_url(self):
|
|
57
|
+
"""Test validation with valid HTTP URL"""
|
|
58
|
+
result = validate_url(None, None, "http://example.com")
|
|
59
|
+
assert result == "http://example.com"
|
|
60
|
+
|
|
61
|
+
def test_invalid_url_no_protocol(self):
|
|
62
|
+
"""Test validation rejects URL without protocol"""
|
|
63
|
+
with pytest.raises(click.BadParameter, match="URL must start with http:// or https://"):
|
|
64
|
+
validate_url(None, None, "example.com")
|
|
65
|
+
|
|
66
|
+
def test_invalid_url_wrong_protocol(self):
|
|
67
|
+
"""Test validation rejects URL with wrong protocol"""
|
|
68
|
+
with pytest.raises(click.BadParameter, match="URL must start with http:// or https://"):
|
|
69
|
+
validate_url(None, None, "ftp://example.com")
|
|
70
|
+
|
|
71
|
+
def test_empty_url(self):
|
|
72
|
+
"""Test validation with empty value"""
|
|
73
|
+
result = validate_url(None, None, None)
|
|
74
|
+
assert result is None
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class TestValidateTimezone:
|
|
78
|
+
"""Test timezone validation"""
|
|
79
|
+
|
|
80
|
+
def test_valid_timezone(self):
|
|
81
|
+
"""Test validation with valid timezone"""
|
|
82
|
+
result = validate_timezone(None, None, "America/New_York")
|
|
83
|
+
assert result == "America/New_York"
|
|
84
|
+
|
|
85
|
+
def test_valid_timezone_utc(self):
|
|
86
|
+
"""Test validation with UTC timezone"""
|
|
87
|
+
result = validate_timezone(None, None, "UTC")
|
|
88
|
+
assert result == "UTC"
|
|
89
|
+
|
|
90
|
+
def test_invalid_timezone(self):
|
|
91
|
+
"""Test validation rejects invalid timezone"""
|
|
92
|
+
with pytest.raises(click.BadParameter, match="Invalid timezone"):
|
|
93
|
+
validate_timezone(None, None, "Invalid/Timezone")
|
|
94
|
+
|
|
95
|
+
def test_empty_timezone(self):
|
|
96
|
+
"""Test validation with empty value"""
|
|
97
|
+
result = validate_timezone(None, None, None)
|
|
98
|
+
assert result is None
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class TestValidateCurrency:
|
|
102
|
+
"""Test currency code validation"""
|
|
103
|
+
|
|
104
|
+
def test_valid_currency(self):
|
|
105
|
+
"""Test validation with valid currency code"""
|
|
106
|
+
result = validate_currency(None, None, "USD")
|
|
107
|
+
assert result == "USD"
|
|
108
|
+
|
|
109
|
+
def test_valid_currency_eur(self):
|
|
110
|
+
"""Test validation with EUR currency"""
|
|
111
|
+
result = validate_currency(None, None, "EUR")
|
|
112
|
+
assert result == "EUR"
|
|
113
|
+
|
|
114
|
+
def test_invalid_currency_too_short(self):
|
|
115
|
+
"""Test validation rejects short currency code"""
|
|
116
|
+
with pytest.raises(click.BadParameter, match="Currency must be 3-letter code"):
|
|
117
|
+
validate_currency(None, None, "US")
|
|
118
|
+
|
|
119
|
+
def test_invalid_currency_too_long(self):
|
|
120
|
+
"""Test validation rejects long currency code"""
|
|
121
|
+
with pytest.raises(click.BadParameter, match="Currency must be 3-letter code"):
|
|
122
|
+
validate_currency(None, None, "USDD")
|
|
123
|
+
|
|
124
|
+
def test_invalid_currency_lowercase(self):
|
|
125
|
+
"""Test validation rejects lowercase currency"""
|
|
126
|
+
with pytest.raises(click.BadParameter, match="Currency must be 3-letter code"):
|
|
127
|
+
validate_currency(None, None, "usd")
|
|
128
|
+
|
|
129
|
+
def test_empty_currency(self):
|
|
130
|
+
"""Test validation with empty value"""
|
|
131
|
+
result = validate_currency(None, None, None)
|
|
132
|
+
assert result is None
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class TestValidateStreamId:
|
|
136
|
+
"""Test stream ID validation"""
|
|
137
|
+
|
|
138
|
+
def test_valid_stream_id(self):
|
|
139
|
+
"""Test validation with valid stream ID"""
|
|
140
|
+
result = validate_stream_id(None, None, "123")
|
|
141
|
+
assert result == "123"
|
|
142
|
+
|
|
143
|
+
def test_invalid_stream_id_non_numeric(self):
|
|
144
|
+
"""Test validation rejects non-numeric stream ID"""
|
|
145
|
+
with pytest.raises(click.BadParameter, match="Stream ID must be numeric"):
|
|
146
|
+
validate_stream_id(None, None, "stream-123")
|