|
1 | 1 | """Unit tests for config.py — build_config and constants.""" |
2 | 2 |
|
3 | 3 | import sys |
4 | | -from unittest.mock import patch |
| 4 | +from unittest.mock import MagicMock, patch |
5 | 5 |
|
6 | 6 | import pytest |
7 | 7 |
|
@@ -120,3 +120,39 @@ def test_import_error_degrades_gracefully(self, monkeypatch): |
120 | 120 | assert mock_log.call_count == 1 |
121 | 121 | assert mock_log.call_args[0][0] == "WARN" |
122 | 122 | assert "boto3 unavailable" in mock_log.call_args[0][1] |
| 123 | + |
| 124 | + def test_access_denied_logged_at_error(self, monkeypatch): |
| 125 | + """Persistent IAM misconfig should page someone — escalate from WARN |
| 126 | + to ERROR so alerts fire.""" |
| 127 | + monkeypatch.delenv("LINEAR_API_TOKEN", raising=False) |
| 128 | + monkeypatch.setenv("LINEAR_API_TOKEN_SECRET_ARN", "arn:aws:sm:::secret/linear") |
| 129 | + |
| 130 | + from botocore.exceptions import ClientError |
| 131 | + |
| 132 | + err = ClientError( |
| 133 | + {"Error": {"Code": "AccessDeniedException", "Message": "no access"}}, |
| 134 | + "GetSecretValue", |
| 135 | + ) |
| 136 | + fake_client = MagicMock() |
| 137 | + fake_client.get_secret_value.side_effect = err |
| 138 | + with patch("boto3.client", return_value=fake_client), patch("config.log") as mock_log: |
| 139 | + assert resolve_linear_api_token() == "" |
| 140 | + assert mock_log.call_count == 1 |
| 141 | + assert mock_log.call_args[0][0] == "ERROR" |
| 142 | + |
| 143 | + def test_other_client_error_logged_at_warn(self, monkeypatch): |
| 144 | + monkeypatch.delenv("LINEAR_API_TOKEN", raising=False) |
| 145 | + monkeypatch.setenv("LINEAR_API_TOKEN_SECRET_ARN", "arn:aws:sm:::secret/linear") |
| 146 | + |
| 147 | + from botocore.exceptions import ClientError |
| 148 | + |
| 149 | + err = ClientError( |
| 150 | + {"Error": {"Code": "ResourceNotFoundException", "Message": "missing"}}, |
| 151 | + "GetSecretValue", |
| 152 | + ) |
| 153 | + fake_client = MagicMock() |
| 154 | + fake_client.get_secret_value.side_effect = err |
| 155 | + with patch("boto3.client", return_value=fake_client), patch("config.log") as mock_log: |
| 156 | + assert resolve_linear_api_token() == "" |
| 157 | + assert mock_log.call_count == 1 |
| 158 | + assert mock_log.call_args[0][0] == "WARN" |
0 commit comments