Coverage for tests / unit / tools / core / test_tool_options_spec.py: 100%
37 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
1"""Tests for ToolOptionsSpec in lintro.tools.core.option_spec module."""
3from __future__ import annotations
5import pytest
6from assertpy import assert_that
8from lintro.tools.core.option_spec import (
9 OptionSpec,
10 OptionType,
11 ToolOptionsSpec,
12 bool_option,
13 int_option,
14 str_option,
15)
18def test_add_returns_self_for_chaining() -> None:
19 """Add method returns self for method chaining."""
20 spec = ToolOptionsSpec()
21 result = spec.add(bool_option("preview", "--preview"))
22 assert_that(result).is_same_as(spec)
25def test_add_multiple_options_via_chaining() -> None:
26 """Multiple options can be added via chaining."""
27 spec = (
28 ToolOptionsSpec()
29 .add(bool_option("preview", "--preview"))
30 .add(int_option("line_length", "--line-length", default=88))
31 .add(str_option("target", "--target"))
32 )
33 assert_that(spec.options).contains_key("preview", "line_length", "target")
36def test_validate_all_valid_values() -> None:
37 """Validate all passes for valid values."""
38 spec = (
39 ToolOptionsSpec()
40 .add(bool_option("preview", "--preview"))
41 .add(int_option("line_length", "--line-length"))
42 )
43 # Should not raise
44 spec.validate_all({"preview": True, "line_length": 88})
47def test_validate_all_rejects_invalid_value() -> None:
48 """Validate all raises for invalid value."""
49 spec = ToolOptionsSpec().add(
50 int_option("line_length", "--line-length", min_value=1),
51 )
52 with pytest.raises(ValueError, match="line_length"):
53 spec.validate_all({"line_length": 0})
56def test_validate_all_checks_required() -> None:
57 """Validate all checks required options."""
58 spec = ToolOptionsSpec().add(
59 OptionSpec(
60 name="required_opt",
61 cli_flag="--required",
62 option_type=OptionType.STR,
63 required=True,
64 ),
65 )
66 with pytest.raises(ValueError, match="required_opt is required"):
67 spec.validate_all({})
70def test_to_cli_args() -> None:
71 """Convert all values to CLI args."""
72 spec = (
73 ToolOptionsSpec()
74 .add(bool_option("preview", "--preview"))
75 .add(int_option("line_length", "--line-length"))
76 )
77 result = spec.to_cli_args({"preview": True, "line_length": 88})
78 assert_that(result).contains("--preview", "--line-length", "88")
81def test_to_cli_args_skips_false_bools() -> None:
82 """CLI args skips False boolean values."""
83 spec = ToolOptionsSpec().add(bool_option("preview", "--preview"))
84 result = spec.to_cli_args({"preview": False})
85 assert_that(result).is_empty()
88def test_get_defaults() -> None:
89 """Get defaults returns default values."""
90 spec = (
91 ToolOptionsSpec()
92 .add(bool_option("preview", "--preview", default=False))
93 .add(int_option("line_length", "--line-length", default=88))
94 .add(str_option("target", "--target"))
95 )
96 defaults = spec.get_defaults()
97 assert_that(defaults).is_equal_to({"preview": False, "line_length": 88})
100def test_get_defaults_empty_when_no_defaults() -> None:
101 """Get defaults returns empty dict when no defaults."""
102 spec = (
103 ToolOptionsSpec()
104 .add(bool_option("preview", "--preview"))
105 .add(str_option("target", "--target"))
106 )
107 assert_that(spec.get_defaults()).is_empty()