Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ __pycache__
node_modules
build/
update.sh

.idea/
.vscode/
2 changes: 1 addition & 1 deletion axe_selenium_python/axe.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def write_results(self, data, name=None):
if name:
filepath = os.path.abspath(name)
else:
filepath = os.path.join(os.path.getcwd(), "results.json")
filepath = os.path.abspath("results.json")

with open(filepath, "w", encoding="utf8") as f:
try:
Expand Down
4 changes: 4 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# pytest.ini
[pytest]
markers =
nondestructive: mark test as nondestructive (does not modify data)
116 changes: 116 additions & 0 deletions tests/test_axe.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,119 @@ def test_write_results_without_filepath(mocker):

assert data == actual_file_contents
assert path.dirname(filename) == cwd


def test_inject_reads_and_executes_script(tmp_path, mocker):
mock_selenium = mocker.MagicMock()
script_file = tmp_path / "axe.min.js"
script_file.write_text("console.log('axe injected');")

axe = Axe(mock_selenium, str(script_file))
axe.inject()

mock_selenium.execute_script.assert_called_once_with("console.log('axe injected');")


def test_inject_missing_script_raises_error(mocker):
mock_selenium = mocker.MagicMock()
axe = Axe(mock_selenium, "nonexistent.js")

with pytest.raises(FileNotFoundError):
axe.inject()


def test_run_with_context_and_options(mocker):
mock_selenium = mocker.MagicMock()
mock_selenium.execute_async_script.return_value = {"passes": []}

axe = Axe(mock_selenium)
context = {"include": [["#main"]]}
options = {"runOnly": {"type": "tag", "values": ["wcag2a"]}}

result = axe.run(context, options)

assert result == {"passes": []}
assert mock_selenium.execute_async_script.called
command = mock_selenium.execute_async_script.call_args[0][0]
assert "axe.run" in command
assert "wcag2a" in command


@pytest.mark.parametrize("context,options", [
({"include": [["#main"]]}, None),
(None, {"runOnly": {"type": "tag", "values": ["wcag2aa"]}}),
])
def test_run_with_single_arg_cases(mocker, context, options):
mock_selenium = mocker.MagicMock()
mock_selenium.execute_async_script.return_value = {"result": "ok"}
axe = Axe(mock_selenium)
axe.run(context, options)
called_script = mock_selenium.execute_async_script.call_args[0][0]
assert "axe.run" in called_script


def test_run_with_invalid_script_raises(mocker):
mock_selenium = mocker.MagicMock()
mock_selenium.execute_async_script.side_effect = Exception("JS failed")

axe = Axe(mock_selenium)
with pytest.raises(Exception, match="JS failed"):
axe.run()


def test_report_generates_expected_string(mocker):
axe = Axe(mocker.MagicMock())
violations = [{
"id": "color-contrast",
"description": "Elements must have sufficient color contrast",
"helpUrl": "https://example.com",
"impact": "serious",
"tags": ["wcag2aa", "contrast"],
"nodes": [{
"target": ["#header"],
"all": [{"message": "Check color contrast"}],
"any": [],
"none": []
}]
}]

report = axe.report(violations)
assert "Found 1 accessibility violations" in report
assert "color-contrast" in report
assert "#header" in report
assert "serious" in report


def test_report_with_empty_list_returns_no_violation_text(mocker):
axe = Axe(mocker.MagicMock())
report = axe.report([])
assert "Found 0 accessibility violations" in report


def test_write_results_default_name(tmp_path, mocker, monkeypatch):
axe = Axe(mocker.MagicMock())
monkeypatch.chdir(tmp_path)
data = {"k": "v"}
axe.write_results(data)
default_file = tmp_path / "results.json"
assert default_file.exists()


def test_write_results_with_invalid_path(mocker):
axe = Axe(mocker.MagicMock())
data = {"key": "value"}

# Attempt writing to directory that does not exist
bad_path = "/invalid_dir/results.json"
with pytest.raises(OSError):
axe.write_results(data, bad_path)


def test_write_results_with_unserializable_data(mocker, tmp_path):
axe = Axe(mocker.MagicMock())
filename = tmp_path / "results.json"

# Functions are not JSON-serializable
data = {"func": lambda x: x}
with pytest.raises(TypeError):
axe.write_results(data, str(filename))