|
| 1 | +import json |
| 2 | + |
1 | 3 | import pytest |
| 4 | +from jsonschema import ValidationError as JsonSchemaValidationError |
| 5 | +from jsonschema import validate |
| 6 | +from pydantic import ValidationError |
2 | 7 |
|
| 8 | +from dbt_jobs_as_code.schemas.config import generate_config_schema |
3 | 9 | from dbt_jobs_as_code.schemas.job import ( |
4 | 10 | IdentifierInfo, |
5 | 11 | JobDefinition, |
@@ -153,3 +159,83 @@ def test_empty_filter(self, test_job_factory): |
153 | 159 | assert len(result) == 1 |
154 | 160 | assert jobs[0] in result |
155 | 161 | assert jobs[1] not in result |
| 162 | + |
| 163 | + |
| 164 | +BASE_JOB_DATA = { |
| 165 | + "name": "Test Job", |
| 166 | + "account_id": 1, |
| 167 | + "project_id": 1, |
| 168 | + "environment_id": 1, |
| 169 | + "settings": {}, |
| 170 | + "triggers": {}, |
| 171 | + "execute_steps": ["dbt build"], |
| 172 | + "run_generate_sources": False, |
| 173 | + "generate_docs": False, |
| 174 | +} |
| 175 | + |
| 176 | + |
| 177 | +class TestScheduleConditionalRequirement: |
| 178 | + """Tests for schedule being optional on ci/merge jobs.""" |
| 179 | + |
| 180 | + # -- Pydantic model tests -- |
| 181 | + |
| 182 | + @pytest.mark.parametrize("job_type", ["ci", "merge"]) |
| 183 | + def test_pydantic_schedule_optional_for_ci_merge(self, job_type): |
| 184 | + job = JobDefinition(**{**BASE_JOB_DATA, "job_type": job_type}) |
| 185 | + assert job.schedule is not None # defaults to Schedule() |
| 186 | + |
| 187 | + @pytest.mark.parametrize("job_type", ["scheduled", "other"]) |
| 188 | + def test_pydantic_schedule_required_for_scheduled_other(self, job_type): |
| 189 | + with pytest.raises(ValidationError, match="schedule"): |
| 190 | + JobDefinition(**{**BASE_JOB_DATA, "job_type": job_type}) |
| 191 | + |
| 192 | + def test_pydantic_schedule_required_when_job_type_absent(self): |
| 193 | + with pytest.raises(ValidationError, match="schedule"): |
| 194 | + JobDefinition(**BASE_JOB_DATA) # job_type defaults to "scheduled" |
| 195 | + |
| 196 | + # -- JSON schema tests -- |
| 197 | + |
| 198 | + @pytest.fixture |
| 199 | + def json_schema(self): |
| 200 | + return json.loads(generate_config_schema()) |
| 201 | + |
| 202 | + def _config_instance(self, job_type=None, include_schedule=False): |
| 203 | + """Build a minimal config dict for JSON schema validation.""" |
| 204 | + job = { |
| 205 | + "name": "Test Job", |
| 206 | + "account_id": 1, |
| 207 | + "project_id": 1, |
| 208 | + "environment_id": 1, |
| 209 | + "settings": {}, |
| 210 | + "triggers": {}, |
| 211 | + "execute_steps": ["dbt build"], |
| 212 | + "run_generate_sources": False, |
| 213 | + "generate_docs": False, |
| 214 | + } |
| 215 | + if job_type is not None: |
| 216 | + job["job_type"] = job_type |
| 217 | + if include_schedule: |
| 218 | + job["schedule"] = {"cron": "0 0 * * *"} |
| 219 | + return {"jobs": {"test_job": job}} |
| 220 | + |
| 221 | + @pytest.mark.parametrize("job_type", ["ci", "merge"]) |
| 222 | + def test_json_schema_schedule_optional_for_ci_merge(self, json_schema, job_type): |
| 223 | + instance = self._config_instance(job_type=job_type, include_schedule=False) |
| 224 | + validate(instance=instance, schema=json_schema) |
| 225 | + |
| 226 | + @pytest.mark.parametrize("job_type", ["scheduled", "other"]) |
| 227 | + def test_json_schema_schedule_required_for_scheduled_other(self, json_schema, job_type): |
| 228 | + instance = self._config_instance(job_type=job_type, include_schedule=False) |
| 229 | + with pytest.raises(JsonSchemaValidationError, match="schedule"): |
| 230 | + validate(instance=instance, schema=json_schema) |
| 231 | + |
| 232 | + def test_json_schema_schedule_required_when_job_type_absent(self, json_schema): |
| 233 | + instance = self._config_instance(include_schedule=False) |
| 234 | + with pytest.raises(JsonSchemaValidationError, match="schedule"): |
| 235 | + validate(instance=instance, schema=json_schema) |
| 236 | + |
| 237 | + @pytest.mark.parametrize("job_type", ["scheduled", "ci", "merge", "other"]) |
| 238 | + def test_json_schema_schedule_accepted_for_all_types(self, json_schema, job_type): |
| 239 | + """Providing schedule is always valid regardless of job_type.""" |
| 240 | + instance = self._config_instance(job_type=job_type, include_schedule=True) |
| 241 | + validate(instance=instance, schema=json_schema) |
0 commit comments