mirror of
https://github.com/esphome/esphome.git
synced 2025-09-03 20:02:22 +01:00
Fix vscode validation not showing error squiggles (#8500)
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
committed by
Jesse Hills
parent
cb0a87c1f9
commit
a7fd6dc382
125
tests/unit_tests/test_vscode.py
Normal file
125
tests/unit_tests/test_vscode.py
Normal file
@@ -0,0 +1,125 @@
|
||||
import json
|
||||
import os
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from esphome import vscode
|
||||
|
||||
|
||||
def _run_repl_test(input_data):
|
||||
"""Reusable test function for different input scenarios."""
|
||||
input_data.append(_exit())
|
||||
with (
|
||||
patch("builtins.input", side_effect=input_data),
|
||||
patch("sys.stdout") as mock_stdout,
|
||||
):
|
||||
args = Mock([])
|
||||
args.ace = False
|
||||
args.substitution = None
|
||||
vscode.read_config(args)
|
||||
|
||||
# Capture printed output
|
||||
full_output = "".join(call[0][0] for call in mock_stdout.write.call_args_list)
|
||||
return full_output.strip().split("\n")
|
||||
|
||||
|
||||
def _validate(file_path: str):
|
||||
return json.dumps({"type": "validate", "file": file_path})
|
||||
|
||||
|
||||
def _file_response(data: str):
|
||||
return json.dumps({"type": "file_response", "content": data})
|
||||
|
||||
|
||||
def _read_file(file_path: str):
|
||||
return json.dumps({"type": "read_file", "path": file_path})
|
||||
|
||||
|
||||
def _exit():
|
||||
return json.dumps({"type": "exit"})
|
||||
|
||||
|
||||
RESULT_NO_ERROR = '{"type": "result", "yaml_errors": [], "validation_errors": []}'
|
||||
|
||||
|
||||
def test_multi_file():
|
||||
source_path = os.path.join("dir_path", "x.yaml")
|
||||
output_lines = _run_repl_test(
|
||||
[
|
||||
_validate(source_path),
|
||||
# read_file x.yaml
|
||||
_file_response("""esphome:
|
||||
name: test1
|
||||
esp8266:
|
||||
board: !secret my_secret_board
|
||||
"""),
|
||||
# read_file secrets.yaml
|
||||
_file_response("""my_secret_board: esp1f"""),
|
||||
]
|
||||
)
|
||||
|
||||
expected_lines = [
|
||||
_read_file(source_path),
|
||||
_read_file(os.path.join("dir_path", "secrets.yaml")),
|
||||
RESULT_NO_ERROR,
|
||||
]
|
||||
|
||||
assert output_lines == expected_lines
|
||||
|
||||
|
||||
def test_shows_correct_range_error():
|
||||
source_path = os.path.join("dir_path", "x.yaml")
|
||||
output_lines = _run_repl_test(
|
||||
[
|
||||
_validate(source_path),
|
||||
# read_file x.yaml
|
||||
_file_response("""esphome:
|
||||
name: test1
|
||||
esp8266:
|
||||
broad: !secret my_secret_board # typo here
|
||||
"""),
|
||||
# read_file secrets.yaml
|
||||
_file_response("""my_secret_board: esp1f"""),
|
||||
]
|
||||
)
|
||||
|
||||
assert len(output_lines) == 3
|
||||
error = json.loads(output_lines[2])
|
||||
validation_error = error["validation_errors"][0]
|
||||
assert validation_error["message"].startswith("[broad] is an invalid option for")
|
||||
range = validation_error["range"]
|
||||
assert range["document"] == source_path
|
||||
assert range["start_line"] == 3
|
||||
assert range["start_col"] == 2
|
||||
assert range["end_line"] == 3
|
||||
assert range["end_col"] == 7
|
||||
|
||||
|
||||
def test_shows_correct_loaded_file_error():
|
||||
source_path = os.path.join("dir_path", "x.yaml")
|
||||
output_lines = _run_repl_test(
|
||||
[
|
||||
_validate(source_path),
|
||||
# read_file x.yaml
|
||||
_file_response("""esphome:
|
||||
name: test1
|
||||
|
||||
packages:
|
||||
board: !include .pkg.esp8266.yaml
|
||||
"""),
|
||||
# read_file .pkg.esp8266.yaml
|
||||
_file_response("""esp8266:
|
||||
broad: esp1f # typo here
|
||||
"""),
|
||||
]
|
||||
)
|
||||
|
||||
assert len(output_lines) == 3
|
||||
error = json.loads(output_lines[2])
|
||||
validation_error = error["validation_errors"][0]
|
||||
assert validation_error["message"].startswith("[broad] is an invalid option for")
|
||||
range = validation_error["range"]
|
||||
assert range["document"] == os.path.join("dir_path", ".pkg.esp8266.yaml")
|
||||
assert range["start_line"] == 1
|
||||
assert range["start_col"] == 2
|
||||
assert range["end_line"] == 1
|
||||
assert range["end_col"] == 7
|
@@ -42,3 +42,23 @@ def test_loading_a_missing_file(fixture_path):
|
||||
yaml_util.load_yaml(yaml_file)
|
||||
except EsphomeError as err:
|
||||
assert "missing.yaml" in str(err)
|
||||
|
||||
|
||||
def test_parsing_with_custom_loader(fixture_path):
|
||||
"""Test custom loader used for vscode connection
|
||||
Default loader is tested in test_include_with_vars
|
||||
"""
|
||||
yaml_file = fixture_path / "yaml_util" / "includetest.yaml"
|
||||
|
||||
loader_calls = []
|
||||
|
||||
def custom_loader(fname):
|
||||
loader_calls.append(fname)
|
||||
|
||||
with open(yaml_file, encoding="utf-8") as f_handle:
|
||||
yaml_util.parse_yaml(yaml_file, f_handle, custom_loader)
|
||||
|
||||
assert len(loader_calls) == 3
|
||||
assert loader_calls[0].endswith("includes/included.yaml")
|
||||
assert loader_calls[1].endswith("includes/list.yaml")
|
||||
assert loader_calls[2].endswith("includes/scalar.yaml")
|
||||
|
Reference in New Issue
Block a user