diff --git a/.gitignore b/.gitignore index c84498f..9a741a1 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ __pycache__ node_modules build/ update.sh + +.idea/ +.vscode/ diff --git a/axe_selenium_python/axe.py b/axe_selenium_python/axe.py index 9ec5616..b044f4d 100755 --- a/axe_selenium_python/axe.py +++ b/axe_selenium_python/axe.py @@ -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: diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..1ceda4d --- /dev/null +++ b/pytest.ini @@ -0,0 +1,4 @@ +# pytest.ini +[pytest] +markers = + nondestructive: mark test as nondestructive (does not modify data) diff --git a/tests/test_axe.py b/tests/test_axe.py index 8d0dcfd..d149a9b 100644 --- a/tests/test_axe.py +++ b/tests/test_axe.py @@ -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))